Blammo 1.0.2.2 → 1.0.2.3
raw patch · 3 files changed
+36/−6 lines, 3 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ Network.Wai.Middleware.Logging: setConfigGetClientIp :: (Request -> Text) -> Config -> Config
Files
- Blammo.cabal +1/−1
- CHANGELOG.md +5/−1
- src/Network/Wai/Middleware/Logging.hs +30/−4
Blammo.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: Blammo-version: 1.0.2.2+version: 1.0.2.3 license: MIT license-file: LICENSE maintainer: Freckle Education
CHANGELOG.md view
@@ -1,4 +1,8 @@-## [_Unreleased_](https://github.com/freckle/blammo/compare/v1.0.2.2...main)+## [_Unreleased_](https://github.com/freckle/blammo/compare/v1.0.2.3...main)++## [v1.0.2.3](https://github.com/freckle/blammo/compare/v1.0.2.2...v1.0.2.3)++- Fix for localhost `clientIp` value in `requestLogger` ([#18](https://github.com/freckle/blammo/issues/18)) ## [v1.0.2.2](https://github.com/freckle/blammo/compare/v1.0.2.1...v1.0.2.2)
src/Network/Wai/Middleware/Logging.hs view
@@ -8,12 +8,14 @@ , Config , defaultConfig , setConfigLogSource+ , setConfigGetClientIp , setConfigGetDestinationIp ) where import Prelude import Blammo.Logging+import Control.Applicative ((<|>)) import Control.Arrow ((***)) import Control.Monad.IO.Unlift (withRunInIO) import Data.Aeson@@ -21,7 +23,10 @@ import qualified Data.Aeson.Compat as KeyMap import Data.ByteString (ByteString) import qualified Data.CaseInsensitive as CI+import Data.List (find)+import Data.Maybe (fromMaybe) import Data.Text (Text, pack)+import qualified Data.Text as T import Data.Text.Encoding (decodeUtf8With) import Data.Text.Encoding.Error (lenientDecode) import Network.HTTP.Types.Header (Header, HeaderName)@@ -87,17 +92,23 @@ data Config = Config { cLogSource :: LogSource+ , cGetClientIp :: Request -> Text , cGetDestinationIp :: Request -> Maybe Text } defaultConfig :: Config defaultConfig = Config { cLogSource = "requestLogger"- , cGetDestinationIp = fmap decodeUtf8 . lookupRequestHeader "x-real-ip"+ , cGetClientIp = \req ->+ fromMaybe (pack $ show $ remoteHost req)+ $ (firstValue =<< lookupRequestHeader "x-forwarded-for" req)+ <|> lookupRequestHeader "x-real-ip" req+ , cGetDestinationIp = lookupRequestHeader "x-real-ip" }+ where firstValue = find (not . T.null) . map T.strip . T.splitOn "," -lookupRequestHeader :: HeaderName -> Request -> Maybe ByteString-lookupRequestHeader h = lookup h . requestHeaders+lookupRequestHeader :: HeaderName -> Request -> Maybe Text+lookupRequestHeader h = fmap decodeUtf8 . lookup h . requestHeaders -- | Change the source used for log messages --@@ -106,10 +117,25 @@ setConfigLogSource :: LogSource -> Config -> Config setConfigLogSource x c = c { cLogSource = x } +-- | Change how the @clientIp@ field is determined+--+-- Default is looking up the first value in @x-forwarded-for@, then the+-- @x-real-ip@ header, then finally falling back to 'Network.Wai.remoteHost'.+--+setConfigGetClientIp :: (Request -> Text) -> Config -> Config+setConfigGetClientIp x c = c { cGetClientIp = x }+ -- | Change how the @destinationIp@ field is determined -- -- Default is looking up the @x-real-ip@ header. --+-- __NOTE__: Our default uses a somewhat loose definition of /destination/. It+-- would be more accurate to report the resolved IP address of the @Host@+-- header, but we don't have that available. Our default of @x-real-ip@ favors+-- containerized Warp on AWS/ECS, where this value holds the ECS target+-- container's IP address. This is valuable debugging information and could, if+-- you squint, be considered a /destination/.+-- setConfigGetDestinationIp :: (Request -> Maybe Text) -> Config -> Config setConfigGetDestinationIp x c = c { cGetDestinationIp = x } @@ -150,7 +176,7 @@ [ "code" .= statusCode status , "message" .= decodeUtf8 (statusMessage status) ]- , "clientIp" .= show (remoteHost req)+ , "clientIp" .= cGetClientIp req , "destinationIp" .= cGetDestinationIp req , "durationMs" .= duration , "requestHeaders"