From 0be629819f90fe71d4a4561d7204d5ea774c00f9 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Fri, 5 Nov 2021 14:01:26 +0100 Subject: [PATCH 1/2] Add ApacheWithSettings OutputFormat to allow request filtering and logging the current user --- stack-lts-14.yaml | 2 + stack.yaml | 1 + wai-extra/ChangeLog.md | 4 ++ .../Network/Wai/Middleware/RequestLogger.hs | 70 +++++++++++++++++-- wai-extra/wai-extra.cabal | 4 +- 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/stack-lts-14.yaml b/stack-lts-14.yaml index de7ae92ae..04027a585 100644 --- a/stack-lts-14.yaml +++ b/stack-lts-14.yaml @@ -23,3 +23,5 @@ extra-deps: - tls-1.5.5@sha256:f6681d6624071211edd509a8f56e0c96b4f003bb349b7dc706d4333775a373c5,6996 - cryptonite-0.29@sha256:147724f6a8e4394fcbd51bf52aba7a8b92d3fc8f42055cd6ca9486655e2ab614,18312 - network-byte-order-0.1.6@sha256:23d8b609ac43a69d04d5e8f411e5f86a0266c0e8b33b65f8c92ebda64273fe3a,1313 +- wai-logger-2.3.7@sha256:19a0dc5122e22d274776d80786fb9501956f5e75b8f82464bbdad5604d154d82,1671 +- fast-logger-3.1.0@sha256:8bdaa5714c5e02bc1b5680a331cee1c22d605b692dfaf60569119b9baf975471,2398 diff --git a/stack.yaml b/stack.yaml index 525465116..805462e2c 100644 --- a/stack.yaml +++ b/stack.yaml @@ -20,3 +20,4 @@ nix: - zlib extra-deps: - http2-3.0.1@sha256:584900e2aacd033d714d4603abd0f9249203a40b5a476889d792ba91661843c0,15814 +- wai-logger-2.3.7@sha256:19a0dc5122e22d274776d80786fb9501956f5e75b8f82464bbdad5604d154d82,1671 diff --git a/wai-extra/ChangeLog.md b/wai-extra/ChangeLog.md index 9612d461a..af332df37 100644 --- a/wai-extra/ChangeLog.md +++ b/wai-extra/ChangeLog.md @@ -1,5 +1,9 @@ # Changelog for wai-extra +## 3.1.8 + +* Added an `ApacheWithSettings` output format for `RequestLogger` that allows request filtering similar to `DetailedWithSettings` and logging of the current user via wai-logger's `initLoggerUser` [#866](https://github.com/yesodweb/wai/pull/866) + ## 3.1.7 * Added new `mPrelogRequests` option to `DetailedSettings` [#857](https://github.com/yesodweb/wai/pull/857) diff --git a/wai-extra/Network/Wai/Middleware/RequestLogger.hs b/wai-extra/Network/Wai/Middleware/RequestLogger.hs index 3b416d688..53f12274d 100644 --- a/wai-extra/Network/Wai/Middleware/RequestLogger.hs +++ b/wai-extra/Network/Wai/Middleware/RequestLogger.hs @@ -13,7 +13,12 @@ module Network.Wai.Middleware.RequestLogger , autoFlush , destination , OutputFormat (..) - , DetailedSettings(..) + , ApacheSettings + , defaultApacheSettings + , setApacheIPAddrSource + , setApacheRequestFilter + , setApacheUserGetter + , DetailedSettings (..) , OutputFormatter , OutputFormatterWithDetails , OutputFormatterWithDetailsAndHeaders @@ -51,16 +56,65 @@ import Network.Wai.Logger import Network.Wai.Middleware.RequestLogger.Internal import Network.Wai.Header (contentLength) import Data.Text.Encoding (decodeUtf8') +import Network.Wai (Request) -- | The logging format. data OutputFormat = Apache IPAddrSource + | ApacheWithSettings ApacheSettings -- ^ @since 3.1.8 | Detailed Bool -- ^ use colors? | DetailedWithSettings DetailedSettings -- ^ @since 3.1.3 | CustomOutputFormat OutputFormatter | CustomOutputFormatWithDetails OutputFormatterWithDetails | CustomOutputFormatWithDetailsAndHeaders OutputFormatterWithDetailsAndHeaders +-- | Settings for the `ApacheWithSettings` `OutputFormat`. This is purposely kept as an abstract data +-- type so that new settings can be added without breaking backwards +-- compatibility. In order to create an 'ApacheSettings' value, use 'defaultApacheSettings' +-- and the various \'setApache\' functions to modify individual fields. For example: +-- +-- > setApacheIPAddrSource FromHeader defaultApacheSettings +-- +-- @since 3.1.8 +data ApacheSettings = ApacheSettings + { apacheIPAddrSource :: IPAddrSource + , apacheUserGetter :: Request -> Maybe BS.ByteString + , apacheRequestFilter :: Request -> Response -> Bool + } + +defaultApacheSettings :: ApacheSettings +defaultApacheSettings = ApacheSettings + { apacheIPAddrSource = FromSocket + , apacheRequestFilter = \_ _ -> True + , apacheUserGetter = \_ -> Nothing + } + +-- | Where to take IP addresses for clients from. See 'IPAddrSource' for more information. +-- +-- Default value: FromSocket +-- +-- @since 3.1.8 +setApacheIPAddrSource :: IPAddrSource -> ApacheSettings -> ApacheSettings +setApacheIPAddrSource x y = y { apacheIPAddrSource = x } + +-- | Function that allows you to filter which requests are logged, based on +-- the request and response +-- +-- Default: log all requests +-- +-- @since 3.1.8 +setApacheRequestFilter :: (Request -> Response -> Bool) -> ApacheSettings -> ApacheSettings +setApacheRequestFilter x y = y { apacheRequestFilter = x } + +-- | Function that allows you to get the current user from the request, which +-- will then be added in the log. +-- +-- Default: return no user +-- +-- @since 3.1.8 +setApacheUserGetter :: (Request -> Maybe BS.ByteString) -> ApacheSettings -> ApacheSettings +setApacheUserGetter x y = y { apacheUserGetter = x } + -- | Settings for the `Detailed` `OutputFormat`. -- -- `mModifyParams` allows you to pass a function to hide confidential @@ -160,7 +214,11 @@ mkRequestLogger RequestLoggerSettings{..} = do Apache ipsrc -> do getdate <- getDateGetter flusher apache <- initLogger ipsrc (LogCallback callback flusher) getdate - return $ apacheMiddleware apache + return $ apacheMiddleware (\_ _ -> True) apache + ApacheWithSettings ApacheSettings{..} -> do + getdate <- getDateGetter flusher + apache <- initLoggerUser (Just apacheUserGetter) apacheIPAddrSource (LogCallback callback flusher) getdate + return $ apacheMiddleware apacheRequestFilter apache Detailed useColors -> let settings = def { useColors = useColors} in detailedMiddleware callbackAndFlush settings @@ -176,10 +234,10 @@ mkRequestLogger RequestLoggerSettings{..} = do getdate <- getDateGetter flusher return $ customMiddlewareWithDetailsAndHeaders callbackAndFlush getdate formatter -apacheMiddleware :: ApacheLoggerActions -> Middleware -apacheMiddleware ala app req sendResponse = app req $ \res -> do - let msize = contentLength (responseHeaders res) - apacheLogger ala req (responseStatus res) msize +apacheMiddleware :: (Request -> Response -> Bool) -> ApacheLoggerActions -> Middleware +apacheMiddleware applyRequestFilter ala app req sendResponse = app req $ \res -> do + when (applyRequestFilter req res) $ + apacheLogger ala req (responseStatus res) $ contentLength (responseHeaders res) sendResponse res customMiddleware :: Callback -> IO ZonedDate -> OutputFormatter -> Middleware diff --git a/wai-extra/wai-extra.cabal b/wai-extra/wai-extra.cabal index d1f426765..92a1b8da4 100644 --- a/wai-extra/wai-extra.cabal +++ b/wai-extra/wai-extra.cabal @@ -1,5 +1,5 @@ Name: wai-extra -Version: 3.1.7 +Version: 3.1.8 Synopsis: Provides some basic WAI handlers and middleware. description: Provides basic WAI handler and middleware functionality: @@ -99,7 +99,7 @@ Library , case-insensitive >= 0.2 , data-default-class , fast-logger >= 2.4.5 - , wai-logger >= 2.3.2 + , wai-logger >= 2.3.7 , ansi-terminal , resourcet >= 0.4.6 && < 1.3 , containers From f8dea787edc32a12c6deea06d2448b0bc540c248 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sun, 2 Jan 2022 18:03:14 +0100 Subject: [PATCH 2/2] Add defaultRequestLoggerSettings export to be able to use ApacheWithSettings without Data.Default --- wai-extra/Network/Wai/Middleware/RequestLogger.hs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/wai-extra/Network/Wai/Middleware/RequestLogger.hs b/wai-extra/Network/Wai/Middleware/RequestLogger.hs index 53f12274d..9ef1250a3 100644 --- a/wai-extra/Network/Wai/Middleware/RequestLogger.hs +++ b/wai-extra/Network/Wai/Middleware/RequestLogger.hs @@ -9,6 +9,7 @@ module Network.Wai.Middleware.RequestLogger -- * Create more versions , mkRequestLogger , RequestLoggerSettings + , defaultRequestLoggerSettings , outputFormat , autoFlush , destination @@ -195,12 +196,15 @@ data RequestLoggerSettings = RequestLoggerSettings , destination :: Destination } +defaultRequestLoggerSettings :: RequestLoggerSettings +defaultRequestLoggerSettings = RequestLoggerSettings + { outputFormat = Detailed True + , autoFlush = True + , destination = Handle stdout + } + instance Default RequestLoggerSettings where - def = RequestLoggerSettings - { outputFormat = Detailed True - , autoFlush = True - , destination = Handle stdout - } + def = defaultRequestLoggerSettings mkRequestLogger :: RequestLoggerSettings -> IO Middleware mkRequestLogger RequestLoggerSettings{..} = do