wai-app-static changes, got directory listing working
This commit is contained in:
parent
5cb8e4a605
commit
240a61a484
@ -4,9 +4,10 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
--
|
--
|
||||||
-- Module : Yesod.Helpers.Static
|
-- Module : Yesod.Static
|
||||||
-- Copyright : Michael Snoyman
|
-- Copyright : Michael Snoyman
|
||||||
-- License : BSD3
|
-- License : BSD3
|
||||||
--
|
--
|
||||||
@ -37,6 +38,8 @@ module Yesod.Static
|
|||||||
, base64md5
|
, base64md5
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Prelude hiding (FilePath)
|
||||||
|
import qualified Prelude
|
||||||
import System.Directory
|
import System.Directory
|
||||||
--import qualified System.Time
|
--import qualified System.Time
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
@ -58,8 +61,11 @@ import Data.Text (Text, pack)
|
|||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
import qualified Data.Map as M
|
import qualified Data.Map as M
|
||||||
--import Data.IORef (readIORef, newIORef, writeIORef)
|
--import Data.IORef (readIORef, newIORef, writeIORef)
|
||||||
import Network.Wai (pathInfo)
|
import Network.Wai (pathInfo, rawPathInfo, responseLBS)
|
||||||
import Data.Char (isLower, isDigit)
|
import Data.Char (isLower, isDigit)
|
||||||
|
import Data.List (foldl')
|
||||||
|
import qualified Data.ByteString as S
|
||||||
|
import Network.HTTP.Types (status301)
|
||||||
|
|
||||||
import Network.Wai.Application.Static
|
import Network.Wai.Application.Static
|
||||||
( StaticSettings (..)
|
( StaticSettings (..)
|
||||||
@ -69,8 +75,7 @@ import Network.Wai.Application.Static
|
|||||||
, embeddedLookup
|
, embeddedLookup
|
||||||
, toEmbedded
|
, toEmbedded
|
||||||
, pathFromPieces
|
, pathFromPieces
|
||||||
, toPiece
|
, toFilePath
|
||||||
, fixPathName
|
|
||||||
)
|
)
|
||||||
|
|
||||||
newtype Static = Static StaticSettings
|
newtype Static = Static StaticSettings
|
||||||
@ -79,28 +84,28 @@ newtype Static = Static StaticSettings
|
|||||||
--
|
--
|
||||||
-- Does not have index files, uses default directory listings and default mime
|
-- Does not have index files, uses default directory listings and default mime
|
||||||
-- type list.
|
-- type list.
|
||||||
static :: FilePath -> Static
|
static :: Prelude.FilePath -> Static
|
||||||
static fp =
|
static fp =
|
||||||
--hashes <- mkHashMap fp
|
--hashes <- mkHashMap fp
|
||||||
Static $ defaultWebAppSettings {
|
Static $ defaultWebAppSettings {
|
||||||
ssFolder = fileSystemLookup fp
|
ssFolder = fileSystemLookup $ toFilePath fp
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Produces a 'Static' based on embedding file contents in the executable at
|
-- | Produces a 'Static' based on embedding file contents in the executable at
|
||||||
-- compile time.
|
-- compile time.
|
||||||
embed :: FilePath -> Q Exp
|
embed :: Prelude.FilePath -> Q Exp
|
||||||
embed fp =
|
embed fp =
|
||||||
[|Static (defaultWebAppSettings
|
[|Static (defaultWebAppSettings
|
||||||
{ ssFolder = embeddedLookup (toEmbedded $(embedDir fp))
|
{ ssFolder = embeddedLookup (toEmbedded $(embedDir fp))
|
||||||
})|]
|
})|]
|
||||||
|
|
||||||
{-
|
{-
|
||||||
publicProduction :: String -> FilePath -> IO Public
|
publicProduction :: String -> Prelude.FilePath -> IO Public
|
||||||
publicProduction root fp = do
|
publicProduction root fp = do
|
||||||
etags <- mkPublicProductionEtag fp
|
etags <- mkPublicProductionEtag fp
|
||||||
return $ public root fp etags
|
return $ public root fp etags
|
||||||
|
|
||||||
publicDevel :: String -> FilePath -> IO Public
|
publicDevel :: String -> Prelude.FilePath -> IO Public
|
||||||
publicDevel root fp = do
|
publicDevel root fp = do
|
||||||
etags <- mkPublicDevelEtag fp
|
etags <- mkPublicDevelEtag fp
|
||||||
return $ public root fp etags
|
return $ public root fp etags
|
||||||
@ -123,15 +128,19 @@ instance RenderRoute StaticRoute where
|
|||||||
renderRoute (StaticRoute x y) = (x, y)
|
renderRoute (StaticRoute x y) = (x, y)
|
||||||
|
|
||||||
instance Yesod master => YesodDispatch Static master where
|
instance Yesod master => YesodDispatch Static master where
|
||||||
|
-- Need to append trailing slash to make relative links work
|
||||||
|
yesodDispatch _ _ [] _ _ = Just $
|
||||||
|
\req -> return $ responseLBS status301 [("Location", rawPathInfo req `S.append` "/")] ""
|
||||||
|
|
||||||
yesodDispatch (Static set) _ textPieces _ _ = Just $
|
yesodDispatch (Static set) _ textPieces _ _ = Just $
|
||||||
\req -> staticApp set req { pathInfo = textPieces }
|
\req -> staticApp set req { pathInfo = textPieces }
|
||||||
|
|
||||||
notHidden :: FilePath -> Bool
|
notHidden :: Prelude.FilePath -> Bool
|
||||||
notHidden ('.':_) = False
|
notHidden ('.':_) = False
|
||||||
notHidden "tmp" = False
|
notHidden "tmp" = False
|
||||||
notHidden _ = True
|
notHidden _ = True
|
||||||
|
|
||||||
getFileListPieces :: FilePath -> IO [[String]]
|
getFileListPieces :: Prelude.FilePath -> IO [[String]]
|
||||||
getFileListPieces = flip go id
|
getFileListPieces = flip go id
|
||||||
where
|
where
|
||||||
go :: String -> ([String] -> [String]) -> IO [[String]]
|
go :: String -> ([String] -> [String]) -> IO [[String]]
|
||||||
@ -149,32 +158,38 @@ getFileListPieces = flip go id
|
|||||||
--
|
--
|
||||||
-- > style_css = StaticRoute ["style.css"] []
|
-- > style_css = StaticRoute ["style.css"] []
|
||||||
-- > js_script_js = StaticRoute ["js/script.js"] []
|
-- > js_script_js = StaticRoute ["js/script.js"] []
|
||||||
staticFiles :: FilePath -> Q [Dec]
|
staticFiles :: Prelude.FilePath -> Q [Dec]
|
||||||
staticFiles dir = mkStaticFiles dir
|
staticFiles dir = mkStaticFiles dir
|
||||||
|
|
||||||
{-
|
{-
|
||||||
publicFiles :: FilePath -> Q [Dec]
|
publicFiles :: Prelude.FilePath -> Q [Dec]
|
||||||
publicFiles dir = mkStaticFiles dir PublicSite
|
publicFiles dir = mkStaticFiles dir PublicSite
|
||||||
-}
|
-}
|
||||||
|
|
||||||
mkHashMap :: FilePath -> IO (M.Map FilePath S8.ByteString)
|
mkHashMap :: Prelude.FilePath -> IO (M.Map Prelude.FilePath S8.ByteString)
|
||||||
mkHashMap dir = do
|
mkHashMap dir = do
|
||||||
fs <- getFileListPieces dir
|
fs <- getFileListPieces dir
|
||||||
hashAlist fs >>= return . M.fromList
|
hashAlist fs >>= return . M.fromList
|
||||||
where
|
where
|
||||||
hashAlist :: [[String]] -> IO [(FilePath, S8.ByteString)]
|
hashAlist :: [[String]] -> IO [(Prelude.FilePath, S8.ByteString)]
|
||||||
hashAlist fs = mapM hashPair fs
|
hashAlist fs = mapM hashPair fs
|
||||||
where
|
where
|
||||||
hashPair :: [String] -> IO (FilePath, S8.ByteString)
|
hashPair :: [String] -> IO (Prelude.FilePath, S8.ByteString)
|
||||||
hashPair pieces = do let file = pathFromRawPieces dir pieces
|
hashPair pieces = do let file = pathFromRawPieces dir pieces
|
||||||
h <- base64md5File file
|
h <- base64md5File file
|
||||||
return (file, S8.pack h)
|
return (file, S8.pack h)
|
||||||
|
|
||||||
|
pathFromRawPieces :: Prelude.FilePath -> [String] -> Prelude.FilePath
|
||||||
|
pathFromRawPieces =
|
||||||
|
foldl' append
|
||||||
|
where
|
||||||
|
append a b = a ++ '/' : b
|
||||||
|
|
||||||
{-
|
{-
|
||||||
mkPublicDevelEtag :: FilePath -> IO StaticSettings
|
mkPublicDevelEtag :: Prelude.FilePath -> IO StaticSettings
|
||||||
mkPublicDevelEtag dir = do
|
mkPublicDevelEtag dir = do
|
||||||
etags <- mkHashMap dir
|
etags <- mkHashMap dir
|
||||||
mtimeVar <- newIORef (M.empty :: M.Map FilePath System.Time.ClockTime)
|
mtimeVar <- newIORef (M.empty :: M.Map Prelude.FilePath System.Time.ClockTime)
|
||||||
return $ ETag $ \f ->
|
return $ ETag $ \f ->
|
||||||
case M.lookup f etags of
|
case M.lookup f etags of
|
||||||
Nothing -> return Nothing
|
Nothing -> return Nothing
|
||||||
@ -187,17 +202,17 @@ mkPublicDevelEtag dir = do
|
|||||||
return $ if newt /= oldt then Nothing else Just checksum
|
return $ if newt /= oldt then Nothing else Just checksum
|
||||||
|
|
||||||
|
|
||||||
mkPublicProductionEtag :: FilePath -> IO StaticSettings
|
mkPublicProductionEtag :: Prelude.FilePath -> IO StaticSettings
|
||||||
mkPublicProductionEtag dir = do
|
mkPublicProductionEtag dir = do
|
||||||
etags <- mkHashMap dir
|
etags <- mkHashMap dir
|
||||||
return $ ETag $ \f -> return . M.lookup f $ etags
|
return $ ETag $ \f -> return . M.lookup f $ etags
|
||||||
-}
|
-}
|
||||||
|
|
||||||
data StaticSite = StaticSite | PublicSite
|
data StaticSite = StaticSite | PublicSite
|
||||||
mkStaticFiles :: FilePath -> Q [Dec]
|
mkStaticFiles :: Prelude.FilePath -> Q [Dec]
|
||||||
mkStaticFiles fp = mkStaticFiles' fp "StaticRoute" True
|
mkStaticFiles fp = mkStaticFiles' fp "StaticRoute" True
|
||||||
|
|
||||||
mkStaticFiles' :: FilePath -- ^ static directory
|
mkStaticFiles' :: Prelude.FilePath -- ^ static directory
|
||||||
-> String -- ^ route constructor "StaticRoute"
|
-> String -- ^ route constructor "StaticRoute"
|
||||||
-> Bool -- ^ append checksum query parameter
|
-> Bool -- ^ append checksum query parameter
|
||||||
-> Q [Dec]
|
-> Q [Dec]
|
||||||
@ -234,7 +249,7 @@ mkStaticFiles' fp routeConName makeHash = do
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
base64md5File :: FilePath -> IO String
|
base64md5File :: Prelude.FilePath -> IO String
|
||||||
base64md5File file = do
|
base64md5File file = do
|
||||||
contents <- L.readFile file
|
contents <- L.readFile file
|
||||||
return $ base64md5 contents
|
return $ base64md5 contents
|
||||||
@ -279,14 +294,10 @@ getStaticHandler static toSubR pieces = do
|
|||||||
|
|
||||||
|
|
||||||
{-
|
{-
|
||||||
calcHash :: FilePath -> IO String
|
calcHash :: Prelude.FilePath -> IO String
|
||||||
calcHash fname =
|
calcHash fname =
|
||||||
withBinaryFile fname ReadMode hashHandle
|
withBinaryFile fname ReadMode hashHandle
|
||||||
where
|
where
|
||||||
hashHandle h = do s <- L.hGetContents h
|
hashHandle h = do s <- L.hGetContents h
|
||||||
return $! base64md5 s
|
return $! base64md5 s
|
||||||
-}
|
-}
|
||||||
|
|
||||||
-- FIXME Greg: Is this correct? Where is this function supposed to be?
|
|
||||||
pathFromRawPieces :: FilePath -> [String] -> FilePath
|
|
||||||
pathFromRawPieces fp = pathFromPieces fp . map (toPiece . pack . fixPathName)
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user