{-# LANGUAGE OverloadedStrings #-} -- | module Network.Wai.Middleware.StaticEmbedded (static) where import Crypto.Hash import Data.ByteArray.Encoding import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import Data.Maybe import qualified Data.Text as T import Network.HTTP.Types (status200, status304) import Network.Mime (defaultMimeLookup) import Network.Wai static :: [(FilePath, B.ByteString)] -> Middleware static files = let files' = map computeEtag files in \app req callback -> fromMaybe (app req callback) $ do let fileName = T.unpack . T.intercalate "/" $ pathInfo req (bs, etag) <- lookup fileName files' let mime = defaultMimeLookup (T.pack fileName) let hdrs = computeHeaders etag return . callback $ if Just etag == lookup "If-None-Match" (requestHeaders req) then responseLBS status304 hdrs BL.empty else responseLBS status200 (("Content-Type", mime) : hdrs) bs where computeHeaders etag = [ ("Cache-Control", "no-transform,public,max-age=300,s-maxage=900") , ("ETag", etag) , ("Vary", "Accept-Encoding") ] computeEtag :: (FilePath, B.ByteString) -> (FilePath, (BL.ByteString, B.ByteString)) computeEtag (fp, bs) = let bs' = BL.fromStrict bs in (fp, (bs', convertToBase Base16 (hashlazy bs' :: Digest SHA1)))