http-reverse-proxy 0.4.3.3 → 0.4.4
raw patch · 4 files changed
+50/−18 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.HTTP.ReverseProxy: rawTcpProxyTo :: (MonadBaseControl IO m, MonadIO m) => ProxyDest -> AppData -> m ()
Files
- ChangeLog.md +5/−0
- Network/HTTP/ReverseProxy.hs +27/−6
- http-reverse-proxy.cabal +1/−1
- test/main.hs +17/−11
ChangeLog.md view
@@ -1,3 +1,8 @@+## 0.4.4++* add `rawTcpProxyTo` which can handle proxying connections without http headers + [#21](https://github.com/fpco/http-reverse-proxy/issues/21) + ## 0.4.3.3 * `fixReqHeaders` may create weird `x-real-ip` header [#19](https://github.com/fpco/http-reverse-proxy/issues/19)
Network/HTTP/ReverseProxy.hs view
@@ -10,6 +10,7 @@ ProxyDest (..) -- * Raw , rawProxyTo+ , rawTcpProxyTo -- * WAI + http-conduit , waiProxyTo , defaultOnExc@@ -121,15 +122,35 @@ where fromClient = DCN.appSource appdata toClient = DCN.appSink appdata- withServer rsrc appdataServer = do- x <- newEmptyMVar- tid1 <- fork $ (rsrc $$+- toServer) `finally` putMVar x True- tid2 <- fork $ (fromServer $$ toClient) `finally` putMVar x False- y <- takeMVar x- killThread $ if y then tid2 else tid1+ withServer rsrc appdataServer = void $ concurrently+ (rsrc $$+- toServer)+ (fromServer $$ toClient) where fromServer = DCN.appSource appdataServer toServer = DCN.appSink appdataServer++-- | Set up a reverse tcp proxy server, which will have a minimal overhead.+--+-- This function uses raw sockets, parsing as little of the request as+-- possible. The workflow is:+--+-- 1. Open up a connection to the given host\/port.+--+-- 2. Pass all bytes across the wire unchanged.+--+-- If you need more control, such as modifying the request or response, use 'waiProxyTo'.+--+-- Since 0.4.4+rawTcpProxyTo :: (MonadBaseControl IO m, MonadIO m)+ => ProxyDest+ -> AppData+ -> m ()+rawTcpProxyTo (ProxyDest host port) appdata = liftIO $+ DCN.runTCPClient (DCN.clientSettings port host) withServer+ where+ withServer appdataServer = void $ concurrently+ (DCN.appSource appdata $$ DCN.appSink appdataServer)+ (DCN.appSource appdataServer $$ DCN.appSink appdata ) -- | Sends a simple 502 bad gateway error message with the contents of the -- exception.
http-reverse-proxy.cabal view
@@ -1,5 +1,5 @@ name: http-reverse-proxy-version: 0.4.3.3+version: 0.4.4 synopsis: Reverse proxy HTTP requests, either over raw sockets or with WAI description: Provides a simple means of reverse-proxying HTTP requests. The raw approach uses the same technique as leveraged by keter, whereas the WAI approach performs full request/response parsing via WAI and http-conduit. homepage: https://github.com/fpco/http-reverse-proxy
test/main.hs view
@@ -28,7 +28,7 @@ import qualified Network.HTTP.Conduit as HC import Network.HTTP.ReverseProxy (ProxyDest (..), WaiProxyResponse (..),- defaultOnExc, rawProxyTo,+ defaultOnExc, rawProxyTo, rawTcpProxyTo, WaiProxySettings (..), SetIpHeader (..), def,@@ -89,16 +89,18 @@ withMan = HC.withManager . (liftIO .) main :: IO ()-main = hspec $ do+main = hspec $ describe "http-reverse-proxy" $ do it "works" $ let content = "mainApp" in withMan $ \manager -> withWApp (\_ f -> f $ responseLBS status200 [] content) $ \port1 -> withWApp (waiProxyTo (const $ return $ WPRProxyDest $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 ->- withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 -> do- lbs <- HC.simpleHttp $ "http://127.0.0.1:" ++ show port3+ withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 ->+ withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+ lbs <- HC.simpleHttp $ "http://127.0.0.1:" ++ show port4 lbs `shouldBe` content+ it "modified path" $ let content = "/somepath" app req f = f $ responseLBS status200 [] $ L8.fromChunks [rawPathInfo req]@@ -108,8 +110,9 @@ in withMan $ \manager -> withWApp app $ \port1 -> withWApp (waiProxyTo (modReq $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 ->- withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 -> do- lbs <- HC.simpleHttp $ "http://127.0.0.1:" ++ show port3+ withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 ->+ withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+ lbs <- HC.simpleHttp $ "http://127.0.0.1:" ++ show port4 S8.concat (L8.toChunks lbs) `shouldBe` content it "deals with streaming data" $ let app _ f = f $ responseStream status200 [] $ \sendChunk flush -> forever $ do@@ -172,8 +175,9 @@ in withMan $ \manager -> withWApp (\r f -> f $ responseLBS status200 [] $ getRealIp r ) $ \port1 -> withWApp (waiProxyTo' (const $ return $ WPRProxyDest $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 ->- withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 -> do- lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port3+ withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 ->+ withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+ lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4 lbs `shouldBe` "127.0.1.1" it "get real ip 2" $ let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)@@ -186,8 +190,9 @@ in withMan $ \manager -> withWApp (\r f -> f $ responseLBS status200 [] $ getRealIp r ) $ \port1 -> withWApp (waiProxyTo' (const $ return $ WPRProxyDest $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 ->- withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 -> do- lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port3+ withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 ->+ withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+ lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4 lbs `shouldBe` "127.0.1.1" it "get real ip 3" $ let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)@@ -201,7 +206,8 @@ withWApp (\r f -> f $ responseLBS status200 [] $ getRealIp r ) $ \port1 -> withWApp (waiProxyTo' (const $ return $ WPRProxyDest $ ProxyDest "127.0.0.1" port1) defaultOnExc manager) $ \port2 -> withCApp (rawProxyTo (const $ return $ Right $ ProxyDest "127.0.0.1" port2)) $ \port3 -> do- lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port3+ withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+ lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4 lbs `shouldBe` "127.0.0.1" {- FIXME describe "waiToRaw" $ do