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

Safe HaskellNone

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

fileServeSource

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.

fileServeLazySource

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.

fileServeStrictSource

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.

serveDirectorySource

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

serveFileSource

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

serveFileFromSource

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.

serveFileUsingSource

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

sendFileResponseSource

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

lazyByteStringResponseSource

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

strictByteStringResponseSource

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

filePathSendFileSource

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.

filePathLazySource

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.

filePathStrictSource

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 StringSource

a Map from file extensions to content-types

example:

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

see also: mimeTypes

mimeTypes :: MimeMapSource

Ready collection of common mime types. Except for the first two entries, the mappings come from an Ubuntu 8.04 /etc/mime.types file.

asContentTypeSource

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 StringSource

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

see also: guessContentTypeM

guessContentTypeM :: Monad m => MimeMap -> FilePath -> m StringSource

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

renderDirectoryContentsSource

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

renderDirectoryContentsTableSource

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 ResponseSource

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 FilePathSource

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"

tryIndexSource

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

doIndexSource

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

isDot :: String -> BoolSource

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.