snap-core-1.0.5.1: Snap: A Haskell Web Framework (core interfaces and types)
Safe HaskellSafe-Inferred
LanguageHaskell2010

Snap.Util.FileServe

Description

Contains web handlers to serve files from a directory.

Example usage:

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Snap.Core           (Snap, route)
import Snap.Http.Server    (quickHttpServe)
import Snap.Util.FileServe

site :: Snap ()
site = route
  [ ("/files",   serveDirectory                            "static")
  , ("/simple",  serveDirectoryWith simpleDirectoryConfig  "static")
  , ("/default", serveDirectoryWith defaultDirectoryConfig "static")
  , ("/fancy",   serveDirectoryWith fancyDirectoryConfig   "static")
  , ("/paper",   serveFile                                 "static/paper.pdf")
  , ("/thesis",  serveFileAs        "application/pdf"      "static/thesis.pdf")
  ]

main :: IO ()
main = quickHttpServe site
Synopsis

Helper functions

getSafePath :: MonadSnap m => m FilePath Source #

Gets a path from the Request using rqPathInfo and makes sure it is safe to use for opening files. A path is safe if it is a relative path and has no ".." elements to escape the intended directory structure.

Example:

ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified Data.ByteString.Char8 as B8
ghci> T.runHandler (T.get "/foo/bar" M.empty) (getSafePath >>= writeBS . B8.pack)
HTTP/1.1 200 OK
server: Snap/test
date: Fri, 08 Aug 2014 16:13:20 GMT

foo/bar
ghci> T.runHandler (T.get "/foo/../bar" M.empty) (getSafePath >>= writeBS . B8.pack)
HTTP/1.1 404 Not Found
...

Configuration for directory serving

type MimeMap = HashMap FilePath ByteString Source #

A type alias for MIME type

type HandlerMap m = HashMap FilePath (FilePath -> m ()) Source #

A type alias for dynamic handlers

data DirectoryConfig m Source #

A collection of options for serving static files out of a directory.

Constructors

DirectoryConfig 

Fields

  • indexFiles :: [FilePath]

    Files to look for when a directory is requested (e.g., index.html)

  • indexGenerator :: FilePath -> m ()

    Handler to generate a directory listing if there is no index.

  • dynamicHandlers :: HandlerMap m

    Map of extensions to pass to dynamic file handlers. This could be used, for example, to implement CGI dispatch, pretty printing of source code, etc.

  • mimeTypes :: MimeMap

    MIME type map to look up content types.

  • preServeHook :: FilePath -> m ()

    Handler that is called before a file is served. It will only be called when a file is actually found, not for generated index pages.

simpleDirectoryConfig :: MonadSnap m => DirectoryConfig m Source #

A very simple configuration for directory serving. This configuration uses built-in MIME types from defaultMimeTypes, and has no index files, index generator, dynamic file handlers, or preServeHook.

defaultDirectoryConfig :: MonadSnap m => DirectoryConfig m Source #

A reasonable default configuration for directory serving. This configuration uses built-in MIME types from defaultMimeTypes, serves common index files index.html and index.htm, but does not autogenerate directory indexes, nor have any dynamic file handlers. The preServeHook will not do anything.

fancyDirectoryConfig :: MonadSnap m => DirectoryConfig m Source #

A more elaborate configuration for file serving. This configuration uses built-in MIME types from defaultMimeTypes, serves common index files index.html and index.htm, and autogenerates directory indexes with a Snap-like feel. It still has no dynamic file handlers, nor preServeHook, which should be added as needed.

Files recognized as indexes include index.html, index.htm, default.html, default.htm, home.html

Example of how the autogenerated directory index looks like:

defaultIndexGenerator Source #

Arguments

:: MonadSnap m 
=> MimeMap

MIME type mapping for reporting types

-> ByteString

Style info to insert in header

-> FilePath

Directory to generate index for

-> m () 

An automatic index generator, which is fairly small and does not rely on any external files (which may not be there depending on external request routing).

A MimeMap is passed in to display the types of files in the directory listing based on their extension. Preferably, this is the same as the map in the DirectoryConfig

The styles parameter allows you to apply styles to the directory listing. The listing itself consists of a table, containing a header row using th elements, and one row per file using td elements, so styles for those pieces may be attached to the appropriate tags.

defaultMimeTypes :: MimeMap Source #

The default set of mime type mappings we use when serving files. Its value:

Map.fromList [
  ( ".asc"     , "text/plain"                                             ),
  ( ".asf"     , "video/x-ms-asf"                                         ),
  ( ".asx"     , "video/x-ms-asf"                                         ),
  ( ".au"      , "audio/basic"                                            ),
  ( ".avi"     , "video/x-msvideo"                                        ),
  ( ".bmp"     , "image/bmp"                                              ),
  ( ".bz2"     , "application/x-bzip"                                     ),
  ( ".c"       , "text/plain"                                             ),
  ( ".class"   , "application/octet-stream"                               ),
  ( ".conf"    , "text/plain"                                             ),
  ( ".cpp"     , "text/plain"                                             ),
  ( ".css"     , "text/css"                                               ),
  ( ".csv"     , "text/csv"                                               ),
  ( ".cxx"     , "text/plain"                                             ),
  ( ".doc"     , "application/msword"                                     ),
  ( ".docx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".wordprocessingml.document"                    ),
  ( ".dotx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".wordprocessingml.template"                    ),
  ( ".dtd"     , "application/xml-dtd"                                    ),
  ( ".dvi"     , "application/x-dvi"                                      ),
  ( ".exe"     , "application/octet-stream"                               ),
  ( ".flv"     , "video/x-flv"                                            ),
  ( ".gif"     , "image/gif"                                              ),
  ( ".gz"      , "application/x-gzip"                                     ),
  ( ".hs"      , "text/plain"                                             ),
  ( ".htm"     , "text/html"                                              ),
  ( ".html"    , "text/html"                                              ),
  ( ".ico"     , "image/x-icon"                                           ),
  ( ".jar"     , "application/x-java-archive"                             ),
  ( ".jpeg"    , "image/jpeg"                                             ),
  ( ".jpg"     , "image/jpeg"                                             ),
  ( ".js"      , "text/javascript"                                        ),
  ( ".json"    , "application/json"                                       ),
  ( ".log"     , "text/plain"                                             ),
  ( ".m3u"     , "audio/x-mpegurl"                                        ),
  ( ".m3u8"    , "application/x-mpegURL"                                  ),
  ( ".mka"     , "audio/x-matroska"                                       ),
  ( ".mk3d"    , "video/x-matroska"                                       ),
  ( ".mkv"     , "video/x-matroska"                                       ),
  ( ".mov"     , "video/quicktime"                                        ),
  ( ".mp3"     , "audio/mpeg"                                             ),
  ( ".mp4"     , "video/mp4"                                              ),
  ( ".mpeg"    , "video/mpeg"                                             ),
  ( ".mpg"     , "video/mpeg"                                             ),
  ( ".ogg"     , "application/ogg"                                        ),
  ( ".pac"     , "application/x-ns-proxy-autoconfig"                      ),
  ( ".pdf"     , "application/pdf"                                        ),
  ( ".png"     , "image/png"                                              ),
  ( ".potx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".presentationml.template"                      ),
  ( ".ppsx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".presentationml.slideshow"                     ),
  ( ".ppt"     , "application/vnd.ms-powerpoint"                          ),
  ( ".pptx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".presentationml.presentation"                  ),
  ( ".ps"      , "application/postscript"                                 ),
  ( ".qt"      , "video/quicktime"                                        ),
  ( ".rtf"     , "text/rtf"                                               ),
  ( ".sig"     , "application/pgp-signature"                              ),
  ( ".sldx"    , S.append "application/vnd.openxmlformats-officedocument"
                          ".presentationml.slide"                         ),
  ( ".spl"     , "application/futuresplash"                               ),
  ( ".svg"     , "image/svg+xml"                                          ),
  ( ".swf"     , "application/x-shockwave-flash"                          ),
  ( ".tar"     , "application/x-tar"                                      ),
  ( ".tar.bz2" , "application/x-bzip-compressed-tar"                      ),
  ( ".tar.gz"  , "application/x-tgz"                                      ),
  ( ".tbz"     , "application/x-bzip-compressed-tar"                      ),
  ( ".text"    , "text/plain"                                             ),
  ( ".tgz"     , "application/x-tgz"                                      ),
  ( ".tif"     , "image/tiff"                                             ),
  ( ".tiff"    , "image/tiff"                                             ),
  ( ".torrent" , "application/x-bittorrent"                               ),
  ( ".ts"      , "video/mp2t"                                             ),
  ( ".txt"     , "text/plain"                                             ),
  ( ".wav"     , "audio/x-wav"                                            ),
  ( ".wax"     , "audio/x-ms-wax"                                         ),
  ( ".webm"    , "video/webm"                                             ),
  ( ".wma"     , "audio/x-ms-wma"                                         ),
  ( ".wmv"     , "video/x-ms-wmv"                                         ),
  ( ".xbm"     , "image/x-xbitmap"                                        ),
  ( ".xlam"    , "application/vnd.ms-excel.addin.macroEnabled.12"         ),
  ( ".xls"     , "application/vnd.ms-excel"                               ),
  ( ".xlsb"    , "application/vnd.ms-excel.sheet.binary.macroEnabled.12"  ),
  ( ".xlsx"    , S.append "application/vnd.openxmlformats-officedocument."
                          "spreadsheetml.sheet"                           ),
  ( ".xltx"    , S.append "application/vnd.openxmlformats-officedocument."
                          "spreadsheetml.template"                        ),
  ( ".xml"     , "text/xml"                                               ),
  ( ".xpm"     , "image/x-xpixmap"                                        ),
  ( ".xwd"     , "image/x-xwindowdump"                                    ),
  ( ".zip"     , "application/zip"                                        ) ]

fileType :: MimeMap -> FilePath -> ByteString Source #

Determine a given file's MIME type from its filename and the provided MIME map.

File servers

serveDirectory Source #

Arguments

:: MonadSnap m 
=> FilePath

Directory to serve from

-> m () 

Serves static files from a directory using the default configuration as given in defaultDirectoryConfig.

serveDirectoryWith Source #

Arguments

:: MonadSnap m 
=> DirectoryConfig m

Configuration options

-> FilePath

Directory to serve from

-> m () 

Serves static files from a directory. Configuration options are passed in a DirectoryConfig that captures various choices about desired behavior. The relative path given in rqPathInfo is searched for a requested file, and the file is served with the appropriate mime type if it is found. Absolute paths and ".." are prohibited to prevent files from being served from outside the sandbox.

serveFile Source #

Arguments

:: MonadSnap m 
=> FilePath

path to file

-> m () 

Serves a single file specified by a full or relative path. If the file does not exist, throws an exception (not that it does not pass to the next handler). The path restrictions on serveDirectory don't apply to this function since the path is not being supplied by the user.

serveFileAs Source #

Arguments

:: MonadSnap m 
=> ByteString

MIME type

-> FilePath

path to file

-> m () 

Same as serveFile, with control over the MIME mapping used.