happstack-server-7.7.0: Web related tools and services.

Safe HaskellNone
LanguageHaskell2010

Happstack.Server.FileServe.BuildingBlocks

Contents

Description

Build your own file serving functions

If the functions in Happstack.Server.FileServe do not quite do you want you can roll your own by reusing pieces from this module.

You will likely want to start by copying the source for a function like, serveDirectory and then modifying it to suit your needs.

Synopsis

High-Level

Serving files from a directory

fileServe Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> [FilePath]

index file names, in case the requested path is a directory

-> FilePath

file/directory to serve

-> m Response 

Deprecated: use serveDirectory instead.

Serve files from a directory and its subdirectories using sendFile.

Usage:

fileServe ["index.html"] "path/to/files/on/disk"

fileServe does not support directory browsing. See serveDirectory

DEPRECATED: use serveDirectory instead.

Note:

The list of index files ["index.html"] is only used to determine what file to show if the user requests a directory. You *do not* need to explicitly list all the files you want to serve.

fileServe' Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> (String -> FilePath -> m Response)

function which takes a content-type and filepath and generates a response (typically filePathSendFile, filePathLazy, or filePathStrict)

-> (FilePath -> m String)

function which returns the mime-type for FilePath -> [FilePath] -- ^ index file names, in case the requested path is a directory

-> (FilePath -> m Response) 
-> FilePath

file/directory to serve

-> m Response 

Serve files from a directory and its subdirectories (parameterizable version)

Parameterize this function to create functions like, fileServe, fileServeLazy, and fileServeStrict

You supply:

  1. a low-level function which takes a content-type and FilePath and generates a Response
  2. a function which determines the content-type from the FilePath
  3. a list of all the default index files

NOTE: unlike fileServe, there are no index files by default. See defaultIxFiles.

fileServeLazy Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> [FilePath]

index file names, in case the requested path is a directory

-> FilePath

file/directory to serve

-> m Response 

Serve files from a directory and its subdirectories (lazy ByteString version).

WARNING: May leak file handles. You should probably use fileServe instead.

fileServeStrict Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> [FilePath]

index file names, in case the next argument is a directory

-> FilePath

file/directory to serve

-> m Response 

Serve files from a directory and its subdirectories (strict ByteString version).

WARNING: the entire file will be read into RAM before being served. You should probably use fileServe instead.

data Browsing Source #

Instances
Enum Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Eq Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Data Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Browsing -> c Browsing #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Browsing #

toConstr :: Browsing -> Constr #

dataTypeOf :: Browsing -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Browsing) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Browsing) #

gmapT :: (forall b. Data b => b -> b) -> Browsing -> Browsing #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Browsing -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Browsing -> r #

gmapQ :: (forall d. Data d => d -> u) -> Browsing -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Browsing -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Browsing -> m Browsing #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Browsing -> m Browsing #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Browsing -> m Browsing #

Ord Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Read Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Show Browsing Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

serveDirectory Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> Browsing

allow directory browsing

-> [FilePath]

index file names, in case the requested path is a directory

-> FilePath

file/directory to serve

-> m Response 

Serve files and directories from a directory and its subdirectories using sendFile.

Usage:

serveDirectory EnableBrowsing ["index.html"] "path/to/files/on/disk"

If the requested path does not match a file or directory on the disk, then serveDirectory calls mzero.

If the requested path is a file then the file is served normally.

If the requested path is a directory, then the result depends on what the first two arguments to the function are.

The first argument controls whether directory browsing is enabled.

The second argument is a list of index files (such as index.html).

When a directory is requested, serveDirectory will first try to find one of the index files (in the order they are listed). If that fails, it will show a directory listing if EnableBrowsing is set, otherwise it will return forbidden "Directory index forbidden".

Here is an explicit list of all the possible outcomes when the argument is a (valid) directory:

DisableBrowsing, empty index file list

This will always return, forbidden "Directory index forbidden"

DisableBrowsing, non-empty index file list
  1. If an index file is found it will be shown.
  2. Otherwise returns, forbidden "Directory index forbidden"
EnableBrowsing, empty index file list

Always shows a directory index.

EnableBrowsing, non-empty index file list
  1. If an index file is found it will be shown
  2. Otherwise shows a directory index

see also: defaultIxFiles, serveFile

serveDirectory' Source #

Arguments

:: (WebMonad Response m, ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> Browsing

allow directory browsing

-> [FilePath]

index file names, in case the requested path is a directory

-> (FilePath -> m String)

function which returns the mime-type for FilePath

-> FilePath

file/directory to serve

-> m Response 

like serveDirectory but with custom mimeTypes

Serving a single file

serveFile Source #

Arguments

:: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> (FilePath -> m String)

function for determining content-type of file. Typically asContentType or guessContentTypeM

-> FilePath

path to the file to serve

-> m Response 

Serve a single, specified file. The name of the file being served is specified explicity. It is not derived automatically from the Request url.

example 1:

Serve as a specific content-type:

serveFile (asContentType "image/jpeg") "/srv/data/image.jpg"

example 2:

Serve guessing the content-type from the extension:

serveFile (guessContentTypeM mimeTypes) "/srv/data/image.jpg"

If the specified path does not exist or is not a file, this function will return mzero.

WARNING: No security checks are performed.

NOTE: alias for serveFileUsing filePathSendFile

serveFileFrom Source #

Arguments

:: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> FilePath

directory wherein served files must be contained

-> (FilePath -> m String)

function for determining content-type of file. Typically asContentType or guessContentTypeM

-> FilePath

path to the file to serve

-> m Response 

Like serveFile, but uses combineSafe to prevent directory traversal attacks when the path to the file is supplied by the user.

serveFileUsing Source #

Arguments

:: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> (String -> FilePath -> m Response)

typically filePathSendFile, filePathLazy, or filePathStrict

-> (FilePath -> m String)

function for determining content-type of file. Typically asContentType or guessContentTypeM

-> FilePath

path to the file to serve

-> m Response 

Serve a single, specified file. The name of the file being served is specified explicity. It is not derived automatically from the Request url.

example 1:

Serve using sendfile() and the specified content-type

serveFileUsing filePathSendFile (asContentType "image/jpeg") "/srv/data/image.jpg"

example 2:

Serve using a lazy ByteString and the guess the content-type from the extension

serveFileUsing filePathLazy (guessContentTypeM mimeTypes) "/srv/data/image.jpg"

WARNING: No security checks are performed.

Low-Level

sendFileResponse Source #

Arguments

:: String

content-type string

-> FilePath

file path for content to send

-> Maybe (UTCTime, Request)

mod-time for the handle (MUST NOT be later than server's time of message origination), incoming request (used to check for if-modified-since header)

-> Integer

offset into Handle

-> Integer

number of bytes to send

-> Response 

Use sendFile to send the contents of a Handle

lazyByteStringResponse Source #

Arguments

:: String

content-type string (e.g. "text/plain; charset=utf-8")

-> ByteString

lazy bytestring content to send

-> Maybe (UTCTime, Request)

mod-time for the bytestring, incoming request (used to check for if-modified-since header)

-> Integer

offset into the bytestring

-> Integer

number of bytes to send (offset + count must be less than or equal to the length of the bytestring)

-> Response 

Send the contents of a Lazy ByteString

strictByteStringResponse Source #

Arguments

:: String

content-type string (e.g. "text/plain; charset=utf-8")

-> ByteString

lazy bytestring content to send

-> Maybe (UTCTime, Request)

mod-time for the bytestring, incoming request (used to check for if-modified-since header)

-> Integer

offset into the bytestring

-> Integer

number of bytes to send (offset + count must be less than or equal to the length of the bytestring)

-> Response 

Send the contents of a Lazy ByteString

filePathSendFile Source #

Arguments

:: (ServerMonad m, MonadIO m) 
=> String

content-type string

-> FilePath

path to file on disk

-> m Response 

Send the specified file with the specified mime-type using sendFile()

NOTE: assumes file exists and is readable by the server. See serveFileUsing.

WARNING: No security checks are performed.

filePathLazy Source #

Arguments

:: (ServerMonad m, MonadIO m) 
=> String

content-type string

-> FilePath

path to file on disk

-> m Response 

Send the specified file with the specified mime-type using lazy ByteStrings

NOTE: assumes file exists and is readable by the server. See serveFileUsing.

WARNING: No security checks are performed.

filePathStrict Source #

Arguments

:: (ServerMonad m, MonadIO m) 
=> String

content-type string

-> FilePath

path to file on disk

-> m Response 

Send the specified file with the specified mime-type using strict ByteStrings

NOTE: assumes file exists and is readable by the server. See serveFileUsing.

WARNING: No security checks are performed.

Content-Type / Mime-Type

type MimeMap = Map String String Source #

a Map from file extensions to content-types

example:

myMimeMap :: MimeMap
myMimeMap = Map.fromList [("gz","application/x-gzip"), ... ]

see also: mimeTypes

mimeTypes :: MimeMap Source #

Ready collection of common mime types. Except for the first two entries, the mappings come from http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/docs/conf/mime.types?view=co

asContentType Source #

Arguments

:: Monad m 
=> String

the content-type to return

-> FilePath -> m String 

returns a specific content type, completely ignoring the FilePath argument.

Use this with serveFile if you want to explicitly specify the content-type.

see also: guessContentTypeM, serveFile

guessContentType :: MimeMap -> FilePath -> Maybe String Source #

try to guess the content-type of a file based on its extension

see also: guessContentTypeM

guessContentTypeM :: Monad m => MimeMap -> FilePath -> m String Source #

try to guess the content-type of a file based on its extension

defaults to "application/octet-stream" if no match was found.

Useful as an argument to serveFile

see also: guessContentType, serveFile

Directory Browsing

data EntryKind Source #

Constructors

File 
Directory 
UnknownKind 
Instances
Enum EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Eq EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Data EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> EntryKind -> c EntryKind #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c EntryKind #

toConstr :: EntryKind -> Constr #

dataTypeOf :: EntryKind -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c EntryKind) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c EntryKind) #

gmapT :: (forall b. Data b => b -> b) -> EntryKind -> EntryKind #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> EntryKind -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> EntryKind -> r #

gmapQ :: (forall d. Data d => d -> u) -> EntryKind -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> EntryKind -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> EntryKind -> m EntryKind #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> EntryKind -> m EntryKind #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> EntryKind -> m EntryKind #

Ord EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Read EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

Show EntryKind Source # 
Instance details

Defined in Happstack.Server.FileServe.BuildingBlocks

renderDirectoryContents Source #

Arguments

:: MonadIO m 
=> FilePath

path to directory on disk

-> [FilePath]

list of entries in that path

-> m Html 

a function to generate an HTML page showing the contents of a directory on the disk

see also: browseIndex, renderDirectoryContentsTable

renderDirectoryContentsTable Source #

Arguments

:: [(FilePath, Maybe UTCTime, Maybe Integer, EntryKind)]

list of files+meta data, see getMetaData

-> Html 

a function to generate an HTML table showing the contents of a directory on the disk

This function generates most of the content of the renderDirectoryContents page. If you want to style the page differently, or add google analytics code, etc, you can just create a new page template to wrap around this HTML.

see also: getMetaData, renderDirectoryContents

Other

blockDotFiles :: (Request -> IO Response) -> Request -> IO Response Source #

Prevents files of the form '.foo' or 'bar/.foo' from being served

defaultIxFiles :: [FilePath] Source #

a list of common index files. Specifically: index.html, index.xml, index.gif

Typically used as an argument to serveDiretory.

combineSafe :: FilePath -> FilePath -> Maybe FilePath Source #

Combine two FilePaths, ensuring that the resulting path leads to a file within the first FilePath.

>>> combineSafe "/var/uploads/" "etc/passwd"
Just "/var/uploads/etc/passwd"
>>> combineSafe "/var/uploads/" "/etc/passwd"
Nothing
>>> combineSafe "/var/uploads/" "../../etc/passwd"
Nothing
>>> combineSafe "/var/uploads/" "../uploads/home/../etc/passwd"
Just "/var/uploads/etc/passwd"

tryIndex Source #

Arguments

:: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> (String -> FilePath -> m Response)

usually filePathSendFile

-> (FilePath -> m String)

function to calculate mime type, usually guessContentTypeM

-> [String]

list of index files. See also defaultIxFiles

-> FilePath

directory to search in

-> m Response 

try to find an index file, calls mzero on failure

doIndex Source #

Arguments

:: (ServerMonad m, FilterMonad Response m, MonadIO m, MonadPlus m) 
=> [FilePath]

list of possible index files (e.g., index.html)

-> MimeMap

see also mimeTypes

-> FilePath

directory on disk to search for index files

-> m Response 

attempt to serve index files

fileNotFound :: (Monad m, FilterMonad Response m) => FilePath -> m Response Source #

return a simple "File not found 404 page."

isDot :: String -> Bool Source #

Returns True if the given String either starts with a . or is of the form "foo/.bar", e.g. the typical *nix convention for hidden files.