{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -- | Middleware for server push learning dependency based on Referer:. module Network.Wai.Middleware.Push.Referer ( -- * Middleware pushOnReferer -- * Making push promise , URLPath , MakePushPromise , defaultMakePushPromise -- * Settings , Settings , M.defaultSettings , makePushPromise , duration , keyLimit , valueLimit ) where import Control.Monad (when) import qualified Data.ByteString as BS import Data.Maybe (isNothing) import Network.HTTP.Types (Status(..)) import Network.Wai import Network.Wai.Handler.Warp hiding (Settings, defaultSettings) import Network.Wai.Internal (Response(..)) import qualified Network.Wai.Middleware.Push.Referer.Manager as M import Network.Wai.Middleware.Push.Referer.ParseURL import Network.Wai.Middleware.Push.Referer.Types -- $setup -- >>> :set -XOverloadedStrings -- | The middleware to push files based on Referer:. -- Learning strategy is implemented in the first argument. pushOnReferer :: Settings -> Middleware pushOnReferer settings app req sendResponse = do mgr <- M.getManager settings app req $ push mgr where path = rawPathInfo req push mgr res@(ResponseFile (Status 200 "OK") _ file Nothing) -- file: /index.html -- path: / -- referer: -- refPath: | isHTML path = do xs <- M.lookup path mgr case xs of [] -> return () ps -> do let h2d = defaultHTTP2Data { http2dataPushPromise = ps } setHTTP2Data req $ Just h2d sendResponse res -- file: /style.css -- path: /style.css -- referer: /index.html -- refPath: / | otherwise = case requestHeaderReferer req of Nothing -> sendResponse res Just referer -> do (mauth,refPath) <- parseUrl referer when ((isNothing mauth || requestHeaderHost req == mauth) && path /= refPath && isHTML refPath) $ do let path' = BS.copy path refPath' = BS.copy refPath mpp <- makePushPromise settings refPath' path' file case mpp of Nothing -> return () Just pp -> M.insert refPath' pp mgr sendResponse res push _ res = sendResponse res isHTML :: URLPath -> Bool isHTML p = ("/" `BS.isSuffixOf` p) || (".html" `BS.isSuffixOf` p) || (".htm" `BS.isSuffixOf` p)