http-reverse-proxy 0.4.3.2 → 0.4.3.3
raw patch · 4 files changed
+61/−4 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ChangeLog.md +4/−0
- Network/HTTP/ReverseProxy.hs +7/−2
- http-reverse-proxy.cabal +1/−1
- test/main.hs +49/−1
ChangeLog.md view
@@ -1,3 +1,7 @@+## 0.4.3.3++* `fixReqHeaders` may create weird `x-real-ip` header [#19](https://github.com/fpco/http-reverse-proxy/issues/19)+ ## 0.4.3.2 * Minor doc cleanup
Network/HTTP/ReverseProxy.hs view
@@ -58,13 +58,15 @@ import Data.Default.Class (Default (..), def) import Data.Functor.Identity (Identity (..)) import Data.IORef-import Data.Maybe (fromMaybe)+import Data.Maybe (fromMaybe, listToMaybe) import Data.Monoid (mappend, mconcat, (<>)) import Data.Set (Set) import qualified Data.Set as Set import Data.Streaming.Network (AppData, readLens) import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TLE+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE import Data.Word8 (isSpace, _colon, _cr) import Network.HTTP.Client (BodyReader, brRead) import qualified Network.HTTP.Client as HC@@ -319,11 +321,14 @@ $ WAI.requestHeaders req where fromSocket = (("X-Real-IP", S8.pack $ showSockAddr $ WAI.remoteHost req):)+ fromForwardedFor = do+ h <- lookup "x-forwarded-for" (WAI.requestHeaders req)+ listToMaybe $ map (TE.encodeUtf8 . T.strip) $ T.splitOn "," $ TE.decodeUtf8 h addXRealIP = case wpsSetIpHeader wps of SIHFromSocket -> fromSocket SIHFromHeader ->- case lookup "x-real-ip" (WAI.requestHeaders req) <|> lookup "X-Forwarded-For" (WAI.requestHeaders req) of+ case lookup "x-real-ip" (WAI.requestHeaders req) <|> fromForwardedFor of Nothing -> fromSocket Just ip -> (("X-Real-IP", ip):) SIHNone -> id
http-reverse-proxy.cabal view
@@ -1,5 +1,5 @@ name: http-reverse-proxy-version: 0.4.3.2+version: 0.4.3.3 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
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} import Blaze.ByteString.Builder (fromByteString)+import Control.Applicative ((<$>)) import Control.Concurrent (forkIO, killThread, newEmptyMVar, putMVar, takeMVar, threadDelay) import Control.Exception (IOException, bracket,@@ -8,6 +9,7 @@ import Control.Monad (forever, unless) import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Resource (runResourceT)+import Data.Maybe (fromMaybe) import qualified Data.ByteString as S import qualified Data.ByteString.Char8 as S8 import qualified Data.ByteString.Lazy.Char8 as L8@@ -27,11 +29,15 @@ import Network.HTTP.ReverseProxy (ProxyDest (..), WaiProxyResponse (..), defaultOnExc, rawProxyTo,+ WaiProxySettings (..),+ SetIpHeader (..),+ def,+ waiProxyToSettings, waiProxyTo) import Network.HTTP.Types (status200, status500) import Network.Socket (sClose) import Network.Wai (rawPathInfo, responseLBS,- responseStream)+ responseStream, requestHeaders) import qualified Network.Wai import Network.Wai.Handler.Warp (defaultSettings, runSettings, setBeforeMainLoop, setPort)@@ -155,6 +161,48 @@ yield "GET / HTTP/1.1\r\nUpgrade: websockET\r\n\r\n" $$ appSink ad yield "hello" $$ appSink ad (appSource ad $$ CB.take 5) >>= (`shouldBe` "HELLO")+ it "get real ip" $+ let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)+ httpWithForwardedFor url = liftIO $ do+ man <- HC.newManager HC.tlsManagerSettings+ oreq <- liftIO $ HC.parseUrl url+ let req = oreq { HC.requestHeaders = [("X-Forwarded-For", "127.0.1.1, 127.0.0.1"), ("Connection", "close")] }+ HC.responseBody <$> HC.httpLbs req man+ waiProxyTo' getDest onError = waiProxyToSettings getDest def { wpsOnExc = onError, wpsSetIpHeader = SIHFromHeader }+ 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+ lbs `shouldBe` "127.0.1.1"+ it "get real ip 2" $+ let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)+ httpWithForwardedFor url = liftIO $ do+ man <- HC.newManager HC.tlsManagerSettings+ oreq <- liftIO $ HC.parseUrl url+ let req = oreq { HC.requestHeaders = [("X-Forwarded-For", "127.0.1.1"), ("Connection", "close")] }+ HC.responseBody <$> HC.httpLbs req man+ waiProxyTo' getDest onError = waiProxyToSettings getDest def { wpsOnExc = onError, wpsSetIpHeader = SIHFromHeader }+ 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+ lbs `shouldBe` "127.0.1.1"+ it "get real ip 3" $+ let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)+ httpWithForwardedFor url = liftIO $ do+ man <- HC.newManager HC.tlsManagerSettings+ oreq <- liftIO $ HC.parseUrl url+ let req = oreq { HC.requestHeaders = [("Connection", "close")] }+ HC.responseBody <$> HC.httpLbs req man+ waiProxyTo' getDest onError = waiProxyToSettings getDest def { wpsOnExc = onError, wpsSetIpHeader = SIHFromHeader }+ 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+ lbs `shouldBe` "127.0.0.1" {- FIXME describe "waiToRaw" $ do it "works" $ do