di-wai (empty) → 0.1
raw patch · 5 files changed
+127/−0 lines, 5 filesdep +basedep +clockdep +df1-wai
Dependencies added: base, clock, df1-wai, di-df1, vault, wai
Files
- CHANGELOG.md +4/−0
- LICENSE.txt +30/−0
- README.md +3/−0
- di-wai.cabal +29/−0
- lib/Di/Wai.hs +61/−0
+ CHANGELOG.md view
@@ -0,0 +1,4 @@+# Version 0.1++* Initial version.+
+ LICENSE.txt view
@@ -0,0 +1,30 @@+Copyright (c) 2024, Renzo Carbonara++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Renzo Carbonara nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,3 @@+# di-wai++`di` logging of `wai` requests and responses.
+ di-wai.cabal view
@@ -0,0 +1,29 @@+cabal-version: 1.18+name: di-wai+version: 0.1+author: Renzo Carbonara+maintainer: renλren.zone+copyright: Renzo Carbonara 2024+license: BSD3+license-file: LICENSE.txt+extra-source-files: README.md CHANGELOG.md+category: Logging+build-type: Simple+synopsis: Di logging for WAI requests and responses+description: Di logging for WAI requests and responses+homepage: https://github.com/k0001/di+bug-reports: https://github.com/k0001/di/issues++library+ hs-source-dirs: lib+ default-language: GHC2021+ exposed-modules: Di.Wai+ build-depends:+ base >=4.9 && <5.0,+ clock,+ df1-wai,+ di-df1,+ vault,+ wai+ ghc-options: -Wall -O2+
+ lib/Di/Wai.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-orphans #-}++-- | This module is designed to be imported as follows:+--+-- @+-- import qualified "Di.Wai"+-- @+module Di.Wai (middleware) where++import Control.Monad.IO.Class+import Data.Foldable+import Data.IORef+import Data.Vault.Lazy qualified as V+import Data.Word+import Df1.Wai qualified+import Di.Df1 qualified+import Network.Wai qualified as Wai+import System.Clock qualified as Clock++-- | Obtain a 'Wai.Middleware' that will log incomming 'Wai.Request's+-- and outgoing 'Wai.Response's.+--+-- @+-- do (__middleware__, __lookup__) <- "Di.Wai".'middleware' di+-- @+--+-- * The obtained @__middleware__@ shall be applied to your 'Wai.Application'.+--+-- * The obtained @__lookup__@ function can be used to obtain the 'Di.Df1.Df1'+-- that includes 'Df1.Path' data about 'Wai.Request'. It returns 'Nothing' if+-- this particular @__middleware__@ was not used on the given 'Wai.Request'.+middleware+ :: (MonadIO m)+ => Di.Df1.Df1+ -> m (Wai.Middleware, Wai.Request -> Maybe Di.Df1.Df1)+middleware di0 = liftIO $ do+ ref :: IORef Word64 <- newIORef 0+ vk :: V.Key Di.Df1.Df1 <- V.newKey+ pure+ ( \app req respond -> do+ t0 <- Clock.getTime Clock.Monotonic+ reqId <- atomicModifyIORef' ref $ \ol -> (ol + 1, ol)+ let di1 =+ foldl'+ (\di (k, v) -> Di.Df1.attr k v di)+ (Di.Df1.push "http" di0)+ (("request", Di.Df1.value reqId) : Df1.Wai.request req)+ Di.Df1.info_ di1 "Request coming in"+ app (req{Wai.vault = V.insert vk di1 (Wai.vault req)}) $ \res -> do+ t1 <- Clock.getTime Clock.Monotonic+ let td = Clock.toNanoSecs t1 - Clock.toNanoSecs t0+ di2 =+ foldl'+ (\di (k, v) -> Di.Df1.attr k v di)+ di1+ (("nanoseconds", Di.Df1.value td) : Df1.Wai.response res)+ Di.Df1.info_ di2 "Response going out"+ respond res+ , \req -> V.lookup vk (Wai.vault req)+ )