packages feed

http-reverse-proxy 0.6.1.0 → 0.6.2.0

raw patch · 4 files changed

+103/−58 lines, 4 filesdep ~blaze-builderdep ~bytestringdep ~case-insensitivenew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: blaze-builder, bytestring, case-insensitive, conduit, conduit-extra, containers, http-client, http-types, network, resourcet, streaming-commons, text, transformers, unliftio, wai, wai-logger, word8

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,3 +1,6 @@+## 0.6.2.0++# Changes internal handling of the `X-Forwarded-For` header (avoids `Text` round-trips, tolerates invalid UTF-8) [#49](https://github.com/fpco/http-reverse-proxy/pull/49)  ## 0.6.1.0 
Network/HTTP/ReverseProxy.hs view
@@ -6,6 +6,7 @@ {-# LANGUAGE LambdaCase            #-} {-# LANGUAGE TupleSections         #-} {-# LANGUAGE CPP                   #-}+ module Network.HTTP.ReverseProxy     ( -- * Types       ProxyDest (..)@@ -63,7 +64,6 @@ 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           GHC.Generics                   (Generic) import           Network.HTTP.Client            (BodyReader, brRead)@@ -79,6 +79,23 @@     , pdPort :: !Int     } deriving (Read, Show, Eq, Ord, Generic) +-- | Trim optional whitespace (OWS) from both ends of a strict 'ByteString'.++-- Per RFC 7230 §3.2.3, OWS = SP / HTAB. This function removes only leading+-- and trailing space (0x20) and horizontal tab (0x09) bytes. It does not+-- modify internal whitespace.++-- On newer @bytestring@ versions (those that provide+-- 'Data.ByteString.Char8.strip') this is a thin wrapper around that+-- function; on older versions we provide a compatible fallback.+trimOWS :: S8.ByteString -> S8.ByteString+#if MIN_VERSION_bytestring(0,12,0)+trimOWS = S8.strip+#else+trimOWS = S8.reverse . S8.dropWhile isOWS . S8.reverse . S8.dropWhile isOWS+  where isOWS c = c == ' ' || c == '\t'+#endif+ -- | Set up a reverse proxy server, which will have a minimal overhead. -- -- This function uses raw sockets, parsing as little of the request as@@ -362,7 +379,7 @@     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+      listToMaybe $ map trimOWS $ S8.split ',' h     addXRealIP =         case wpsSetIpHeader wps of             SIHFromSocket -> fromSocket
http-reverse-proxy.cabal view
@@ -1,64 +1,74 @@-name:                http-reverse-proxy-version:             0.6.1.0-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-license:             BSD3-license-file:        LICENSE-author:              Michael Snoyman-maintainer:          michael@fpcomplete.com-category:            Web-build-type:          Simple-cabal-version:       >=1.10-extra-source-files:  README.md ChangeLog.md+name:               http-reverse-proxy+version:            0.6.2.0+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+license:            BSD3+license-file:       LICENSE+author:             Michael Snoyman+maintainer:         michael@fpcomplete.com+category:           Web+build-type:         Simple+cabal-version:      >=1.10+extra-source-files:+  ChangeLog.md+  README.md+ library-  default-language:    Haskell2010-  exposed-modules:     Network.HTTP.ReverseProxy-  other-modules:       Paths_http_reverse_proxy-  if impl(ghc < 8)+  default-language: Haskell2010+  exposed-modules:  Network.HTTP.ReverseProxy+  other-modules:    Paths_http_reverse_proxy++  if impl(ghc <8)     buildable: False-  build-depends:       base                   >= 4.11   && < 5-                     , text                   >= 0.11-                     , bytestring             >= 0.9-                     , case-insensitive       >= 0.4-                     , http-types             >= 0.6-                     , word8                  >= 0.0-                     , blaze-builder          >= 0.3-                     , http-client            >= 0.3-                     , wai                    >= 3.0-                     , network-                     , conduit                >= 1.3-                     , conduit-extra-                     , wai-logger-                     , resourcet-                     , containers-                     , unliftio               >= 0.2-                     , transformers-                     , streaming-commons +  build-depends:+      base               >=4.11 && <5+    , blaze-builder      >=0.3  && <0.5+    , bytestring         >=0.9  && <0.13+    , case-insensitive   >=0.4  && <1.3+    , conduit            >=1.3  && <1.4+    , conduit-extra      <1.4+    , containers         <0.9+    , http-client        >=0.3  && <0.8+    , http-types         >=0.6  && <0.13+    , network            <3.3+    , resourcet          <1.4+    , streaming-commons  <0.3+    , text               >=0.11 && <2.2+    , transformers       <0.7+    , unliftio           >=0.2  && <0.3+    , wai                >=3.0  && <3.3+    , wai-logger         >=2.0  && <2.6+    , word8              >=0.0  && <0.2+ test-suite test-    default-language:    Haskell2010-    type: exitcode-stdio-1.0-    main-is: main.hs-    hs-source-dirs: test-    build-depends: base < 10-                 , http-reverse-proxy-                 , wai-                 , http-types-                 , hspec                      >= 1.3-                 , warp                       >= 2.1-                 , bytestring-                 , conduit                    >= 1.1-                 , conduit-extra-                 , blaze-builder-                 , transformers-                 , unliftio-                 , network-                 , http-conduit               >= 2.3-                 , resourcet-                 , streaming-commons+  default-language: Haskell2010+  type:             exitcode-stdio-1.0+  main-is:          main.hs+  hs-source-dirs:   test+  build-depends:+      base                <10+    , blaze-builder+    , bytestring+    , conduit             >=1.1+    , conduit-extra+    , hspec               >=1.3+    , http-conduit        >=2.3+    , http-reverse-proxy+    , http-types+    , network+    , resourcet+    , streaming-commons+    , transformers+    , unliftio+    , wai+    , warp                >=2.1  source-repository head   type:     git-  location: git://github.com/fpco/http-reverse-proxy.git+  location: https://github.com/fpco/http-reverse-proxy.git
test/main.hs view
@@ -211,6 +211,21 @@                 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"+        it "doesn't fail on invalid utf8 in x-forwarded-for header" $+            let getRealIp req = L8.fromStrict $ fromMaybe "" $ lookup "x-real-ip" (requestHeaders req)+                httpWithForwardedFor url = liftIO $ do+                  man <- HC.newManager HC.tlsManagerSettings+                  oreq <- liftIO $ HC.parseUrlThrow url+                  let req = oreq { HC.requestHeaders = [("X-Forwarded-For", "\xbf\xf0\x9f\x92\xa1"), ("Connection", "close")] }+                  HC.responseBody <$> HC.httpLbs req man+                waiProxyTo' getDest onError = waiProxyToSettings getDest defaultWaiProxySettings { 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 ->+                withCApp (rawTcpProxyTo (ProxyDest "127.0.0.1" port3)) $ \port4 -> do+                    lbs <- httpWithForwardedFor $ "http://127.0.0.1:" ++ show port4+                    lbs `shouldBe` "\xbf\xf0\x9f\x92\xa1"         it "performs log action" $           let ioref :: IO (IORef Int)               ioref = newIORef 1