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@. 62type Pieces = [Piece] 63 64-- | Values for the max-age component of the cache-control response header. 65data MaxAge = NoMaxAge -- ^ no cache-control set 66 | MaxAgeSeconds Int -- ^ set to the given number of seconds 67 | MaxAgeForever -- ^ essentially infinite caching; in reality, probably one year 68 69-- | Just the name of a folder. 70type FolderName = Piece 71 72-- | Represent contents of a single folder, which can be itself either a file 73-- or a folder. 74data Folder = Folder 75 { folderContents :: [Either FolderName File] 76 } 77 78-- | Information on an individual file. 79data File = File 80 { -- | Size of file in bytes 81 fileGetSize :: Integer 82 -- | How to construct a WAI response for this file. Some files are stored 83 -- on the filesystem and can use @ResponseFile@, while others are stored 84 -- in memory and should use @ResponseBuilder@. 85 , fileToResponse :: H.Status -> H.ResponseHeaders -> W.Response 86 -- | Last component of the filename. 87 , fileName :: Piece 88 -- | Calculate a hash of the contents of this file, such as for etag. 89 , fileGetHash :: IO (Maybe ByteString) 90 -- | Last modified time, used for both display in listings and if-modified-since. 91 , fileGetModified :: Maybe EpochTime 92 } 93 94-- | Result of looking up a file in some storage backend. 95-- 96-- The lookup is either a file or folder, or does not exist. 97data LookupResult = LRFile File 98 | LRFolder Folder 99 | LRNotFound 100 101-- | How to construct a directory listing page for the given request path and 102-- the resulting folder. 103type Listing = Pieces -> Folder -> IO Builder 104 105-- | All of the settings available to users for tweaking wai-app-static. 106-- 107-- Note that you should use the settings type approach for modifying values. 108-- See <http://www.yesodweb.com/book/settings-types> for more information. 109data StaticSettings = StaticSettings 110 { 111 -- | Lookup a single file or folder. This is how you can control storage 112 -- backend (filesystem, embedded, etc) and where to lookup. 113 ssLookupFile :: Pieces -> IO LookupResult 114 115 -- | Determine the mime type of the given file. Note that this function 116 -- lives in @IO@ in case you want to perform more complicated mimetype 117 -- analysis, such as via the @file@ utility. 118 , ssGetMimeType :: File -> IO MimeType 119 120 -- | Ordered list of filenames to be used for indices. If the user 121 -- requests a folder, and a file with the given name is found in that 122 -- folder, that file is served. This supercedes any directory listing. 123 , ssIndices :: [Piece] 124 125 -- | How to perform a directory listing. Optional. Will be used when the 126 -- user requested a folder. 127 , ssListing :: Maybe Listing 128 129 -- | Value to provide for max age in the cache-control. 130 , ssMaxAge :: MaxAge 131 132 -- | Given a requested path and a new destination, construct a string 133 -- that will go there. Default implementation will use relative paths. 134 , ssMkRedirect :: Pieces -> ByteString -> ByteString 135 136 -- | If @True@, send a redirect to the user when a folder is requested 137 -- and an index page should be displayed. When @False@, display the 138 -- content immediately. 139 , ssRedirectToIndex :: Bool 140 141 -- | Prefer usage of etag caching to last-modified caching. 142 , ssUseHash :: Bool 143 144 -- | Force a trailing slash at the end of directories 145 , ssAddTrailingSlash :: Bool 146 147 -- | Optional `W.Application` to be used in case of 404 errors 148 -- 149 -- Since 3.1.3 150 , ss404Handler :: Maybe W.Application 151 } 152