1module WaiAppStatic.Types 2 ( -- * Pieces 3 Piece 4 , toPiece 5 , fromPiece 6 , unsafeToPiece 7 , Pieces 8 , toPieces 9 -- * Caching 10 , MaxAge (..) 11 -- * File\/folder serving 12 , FolderName 13 , Folder (..) 14 , File (..) 15 , LookupResult (..) 16 , Listing 17 -- * Settings 18 , StaticSettings (..) 19 ) where 20 21import Data.Text (Text) 22import qualified Network.HTTP.Types as H 23import qualified Network.Wai as W 24import Data.ByteString (ByteString) 25import System.Posix.Types (EpochTime) 26import qualified Data.Text as T 27import Data.ByteString.Builder (Builder) 28import Network.Mime (MimeType) 29 30-- | An individual component of a path, or of a filepath. 31-- 32-- This is the core type used by wai-app-static for doing lookups. It provides 33-- a smart constructor to avoid the possibility of constructing unsafe path 34-- segments (though @unsafeToPiece@ can get around that as necessary). 35-- 36-- Individual file lookup backends must know how to convert from a @Piece@ to 37-- their storage system. 38newtype Piece = Piece { fromPiece :: Text } 39 deriving (Show, Eq, Ord) 40 41-- | Smart constructor for a @Piece@. Won\'t allow unsafe components, such as 42-- pieces beginning with a period or containing a slash. This /will/, however, 43-- allow null pieces. 44toPiece :: Text -> Maybe Piece 45toPiece t 46 | T.null t = Just $ Piece t 47 | T.head t == '.' = Nothing 48 | T.any (== '/') t = Nothing 49 | otherwise = Just $ Piece t 50 51-- | Construct a @Piece@ without input validation. 52unsafeToPiece :: Text -> Piece 53unsafeToPiece = Piece 54 55-- | Call @toPiece@ on a list. 56-- 57-- > toPieces = mapM toPiece 58toPieces :: [Text] -> Maybe Pieces 59toPieces = mapM toPiece 60 61-- | Request coming from a user. Corresponds to @pathInfo@. 62-- 63-- The root path is the empty list. 64type Pieces = [Piece] 65 66-- | Values for the max-age component of the cache-control response header. 67data MaxAge = NoMaxAge -- ^ no cache-control set 68 | MaxAgeSeconds Int -- ^ set to the given number of seconds 69 | MaxAgeForever -- ^ essentially infinite caching; in reality, probably one year 70 71-- | Just the name of a folder. 72type FolderName = Piece 73 74-- | Represent contents of a single folder, which can be itself either a file 75-- or a folder. 76data Folder = Folder 77 { folderContents :: [Either FolderName File] 78 } 79 80-- | Information on an individual file. 81data File = File 82 { -- | Size of file in bytes 83 fileGetSize :: Integer 84 -- | How to construct a WAI response for this file. Some files are stored 85 -- on the filesystem and can use @ResponseFile@, while others are stored 86 -- in memory and should use @ResponseBuilder@. 87 , fileToResponse :: H.Status -> H.ResponseHeaders -> W.Response 88 -- | Last component of the filename. 89 , fileName :: Piece 90 -- | Calculate a hash of the contents of this file, such as for etag. 91 , fileGetHash :: IO (Maybe ByteString) 92 -- | Last modified time, used for both display in listings and if-modified-since. 93 , fileGetModified :: Maybe EpochTime 94 } 95 96-- | Result of looking up a file in some storage backend. 97-- 98-- The lookup is either a file or folder, or does not exist. 99data LookupResult = LRFile File 100 | LRFolder Folder 101 | LRNotFound 102 103-- | How to construct a directory listing page for the given request path and 104-- the resulting folder. 105type Listing = Pieces -> Folder -> IO Builder 106 107-- | All of the settings available to users for tweaking wai-app-static. 108-- 109-- Note that you should use the settings type approach for modifying values. 110-- See <http://www.yesodweb.com/book/settings-types> for more information. 111data StaticSettings = StaticSettings 112 { 113 -- | Lookup a single file or folder. This is how you can control storage 114 -- backend (filesystem, embedded, etc) and where to lookup. 115 ssLookupFile :: Pieces -> IO LookupResult 116 117 -- | Determine the mime type of the given file. Note that this function 118 -- lives in @IO@ in case you want to perform more complicated mimetype 119 -- analysis, such as via the @file@ utility. 120 , ssGetMimeType :: File -> IO MimeType 121 122 -- | Ordered list of filenames to be used for indices. If the user 123 -- requests a folder, and a file with the given name is found in that 124 -- folder, that file is served. This supercedes any directory listing. 125 , ssIndices :: [Piece] 126 127 -- | How to perform a directory listing. Optional. Will be used when the 128 -- user requested a folder. 129 , ssListing :: Maybe Listing 130 131 -- | Value to provide for max age in the cache-control. 132 , ssMaxAge :: MaxAge 133 134 -- | Given a requested path and a new destination, construct a string 135 -- that will go there. Default implementation will use relative paths. 136 , ssMkRedirect :: Pieces -> ByteString -> ByteString 137 138 -- | If @True@, send a redirect to the user when a folder is requested 139 -- and an index page should be displayed. When @False@, display the 140 -- content immediately. 141 , ssRedirectToIndex :: Bool 142 143 -- | Prefer usage of etag caching to last-modified caching. 144 , ssUseHash :: Bool 145 146 -- | Force a trailing slash at the end of directories 147 , ssAddTrailingSlash :: Bool 148 149 -- | Optional `W.Application` to be used in case of 404 errors 150 -- 151 -- Since 3.1.3 152 , ss404Handler :: Maybe W.Application 153 } 154