packages feed

wai-http2-extra 0.0.2 → 0.1.0

raw patch · 2 files changed

+65/−31 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Network.Wai.Middleware.Push.Referer: data Settings
+ Network.Wai.Middleware.Push.Referer: defaultSettings :: Settings
+ Network.Wai.Middleware.Push.Referer: duration :: Settings -> Int
+ Network.Wai.Middleware.Push.Referer: keyLimit :: Settings -> Int
+ Network.Wai.Middleware.Push.Referer: makePushPromise :: Settings -> MakePushPromise
+ Network.Wai.Middleware.Push.Referer: valueLimit :: Settings -> Int
- Network.Wai.Middleware.Push.Referer: pushOnReferer :: MakePushPromise -> Middleware
+ Network.Wai.Middleware.Push.Referer: pushOnReferer :: Settings -> Middleware

Files

Network/Wai/Middleware/Push/Referer.hs view
@@ -1,18 +1,28 @@-{-# LANGUAGE BangPatterns, OverloadedStrings #-}+{-# LANGUAGE BangPatterns, OverloadedStrings, RecordWildCards #-}  -- | Middleware for server push learning dependency based on Referer:. module Network.Wai.Middleware.Push.Referer (+  -- * Middleware     pushOnReferer+  -- * Making push promise+  , URLPath   , MakePushPromise   , defaultMakePushPromise-  , URLPath+  -- * Settings+  , Settings+  , defaultSettings+  , makePushPromise+  , duration+  , keyLimit+  , valueLimit   ) where -import Control.Monad (when)+import Control.Monad (when, unless) import Control.Reaper import Data.ByteString (ByteString) import qualified Data.ByteString as BS import Data.ByteString.Internal (ByteString(..), memchr)+import Data.IORef import Data.Maybe (isNothing) import Data.Word (Word8) import Data.Word8@@ -21,7 +31,7 @@ import Foreign.Storable (peek) import Network.HTTP.Types (Status(..)) import Network.Wai-import Network.Wai.Handler.Warp+import Network.Wai.Handler.Warp hiding (Settings, defaultSettings) import Network.Wai.Internal (Response(..)) import System.IO.Unsafe (unsafePerformIO) @@ -47,36 +57,61 @@  type Cache = M.LimitMultiMap URLPath PushPromise -emptyCache :: Cache-emptyCache = M.empty 20 20 -- FIXME hard-coding+initialized :: IORef Bool+initialized = unsafePerformIO $ newIORef False+{-# NOINLINE initialized #-} -cacheReaper :: Reaper Cache (URLPath,PushPromise)-cacheReaper = unsafePerformIO $ mkReaper settings+cacheReaper :: IORef (Maybe (Reaper Cache (URLPath,PushPromise)))+cacheReaper = unsafePerformIO $ newIORef Nothing {-# NOINLINE cacheReaper #-} -settings :: ReaperSettings Cache (URLPath,PushPromise)-settings = defaultReaperSettings {-      reaperAction = \_ -> return (\_ -> emptyCache)-    , reaperCons   = M.insert-    , reaperNull   = M.isEmpty-    , reaperEmpty  = emptyCache---  , reaperDelay  = 30000000 -- FIXME hard-coding-    }+-- | Settings for server push based on Referer:.+data Settings = Settings {+    makePushPromise :: MakePushPromise -- ^ Default: 'defaultMakePushPromise'+  , duration :: Int -- ^ Duration (in micro seconds) to keep the learning information. The information completely cleared every this duration. Default: 30000000+  , keyLimit :: Int -- ^ Max number of keys (e.g. index.html) in the learning information. Default: 20+  , valueLimit :: Int -- ^ Max number of values (e.g. style.css) in the learning information. Default: 20+  } +-- | Default settings.+defaultSettings :: Settings+defaultSettings = Settings {+    makePushPromise = defaultMakePushPromise+  , duration = 30000000+  , keyLimit = 20+  , valueLimit = 20+  }++tryInitialize :: Settings -> IO ()+tryInitialize Settings{..} = do+    isInitialized <- atomicModifyIORef' initialized $ \x -> (True, x)+    unless isInitialized $ do+        reaper <- mkReaper settings+        writeIORef cacheReaper (Just reaper)+  where+    emptyCache = M.empty keyLimit valueLimit+    settings :: ReaperSettings Cache (URLPath,PushPromise)+    settings = defaultReaperSettings {+        reaperAction = \_ -> return (\_ -> emptyCache)+      , reaperCons   = M.insert+      , reaperNull   = M.isEmpty+      , reaperEmpty  = emptyCache+      , reaperDelay  = duration+      }+ -- | The middleware to push files based on Referer:. --   Learning strategy is implemented in the first argument.------   Cache of learning information is kept for 30 seconds---   and cleared completely.---   Max number of keys (e.g. index.html) is 20.---   Max number of values (e.g. style.css) for each key is 20.---   These numbers are hard-coded at this moment.-pushOnReferer :: MakePushPromise -> Middleware-pushOnReferer func app req sendResponse = app req push+pushOnReferer :: Settings -> Middleware+pushOnReferer settings@Settings{..} app req sendResponse = do+    tryInitialize settings+    mreaper <- readIORef cacheReaper+    case mreaper of+        Nothing     -> app req sendResponse+        Just reaper -> app req (push reaper)   where-    push res@(ResponseFile (Status 200 "OK") _ file Nothing) = do+    push reaper res@(ResponseFile (Status 200 "OK") _ file Nothing) = do         let !path = rawPathInfo req-        m <- reaperRead cacheReaper+        m <- reaperRead reaper         case M.lookup path m of             [] -> case requestHeaderReferer req of                 Nothing      -> return ()@@ -85,15 +120,15 @@                     when (isNothing mauth                        || requestHeaderHost req == mauth) $ do                         when (path /= refPath) $ do -- just in case-                            mpp <- func refPath path file+                            mpp <- makePushPromise refPath path file                             case mpp of                                 Nothing -> return ()-                                Just pp -> reaperAdd cacheReaper (refPath,pp)+                                Just pp -> reaperAdd reaper (refPath,pp)             ps -> do                 let !h2d = defaultHTTP2Data { http2dataPushPromise = ps}                 setHTTP2Data req (Just h2d)         sendResponse res-    push res = sendResponse res+    push _ res = sendResponse res   -- | Learn if the file to be pushed is CSS (.css) or JavaScript (.js) file@@ -197,4 +232,3 @@         !off = p1 `minusPtr` p0         !siz = p2 `minusPtr` p1         !path = PS fptr0 off siz-
wai-http2-extra.cabal view
@@ -1,5 +1,5 @@ Name:                wai-http2-extra-Version:             0.0.2+Version:             0.1.0 Synopsis:            WAI utilities for HTTP/2 License:             MIT License-file:        LICENSE