packages feed

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 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)+      )