diff --git a/doc/tutorial/Javascript.lhs b/doc/tutorial/Javascript.lhs index 2d9ab6bd..07691372 100644 --- a/doc/tutorial/Javascript.lhs +++ b/doc/tutorial/Javascript.lhs @@ -136,7 +136,7 @@ server = randomPoint server' :: Server API' server' = server - :<|> serveDirectory "static" + :<|> serveDirectoryWebApp "static" app :: Application app = serve api' server' diff --git a/doc/tutorial/Server.lhs b/doc/tutorial/Server.lhs index b4014263..cec9d059 100644 --- a/doc/tutorial/Server.lhs +++ b/doc/tutorial/Server.lhs @@ -787,10 +787,10 @@ directory serving WAI application, namely: ``` haskell ignore -- exported by Servant and Servant.Server -serveDirectory :: FilePath -> Server Raw +serveDirectoryWebApp :: FilePath -> Server Raw ``` -`serveDirectory`'s argument must be a path to a valid directory. +`serveDirectoryWebApp`'s argument must be a path to a valid directory. Here's an example API that will serve some static files: @@ -807,7 +807,7 @@ staticAPI = Proxy ``` haskell server7 :: Server StaticAPI -server7 = serveDirectory "static-files" +server7 = serveDirectoryWebApp "static-files" app3 :: Application app3 = serve staticAPI server7 @@ -821,6 +821,10 @@ In other words: If a client requests `/static/foo.txt`, the server will look for `./static-files/foo.txt`. If that file exists it'll succeed and serve the file. If it doesn't exist, the handler will fail with a `404` status code. +`serveDirectoryWebApp` uses some standard settings that fit the use case of +serving static files for most web apps. You can find out about the other +options in the documentation of the `Servant.Utils.StaticFiles` module. + ## Nested APIs Let's see how you can define APIs in a modular way, while avoiding repetition. diff --git a/servant-server/src/Servant/Utils/StaticFiles.hs b/servant-server/src/Servant/Utils/StaticFiles.hs index 08d01ada..30485c74 100644 --- a/servant-server/src/Servant/Utils/StaticFiles.hs +++ b/servant-server/src/Servant/Utils/StaticFiles.hs @@ -1,20 +1,27 @@ {-# LANGUAGE CPP #-} --- | This module defines a sever-side handler that lets you serve static files. +-- | This module defines server-side handlers that lets you serve static files. -- --- - 'serveDirectory' lets you serve anything that lives under a particular --- directory on your filesystem. -module Servant.Utils.StaticFiles ( - serveDirectory, - ) where +-- The most common needs for a web application are covered by +-- 'serveDirectoryWebApp`, but the other variants allow you to use +-- different `StaticSettings` and 'serveDirectoryWith' even allows you +-- to specify arbitrary 'StaticSettings' to be used for serving static files. +module Servant.Utils.StaticFiles + ( serveDirectoryWebApp + , serveDirectoryWebAppLookup + , serveDirectoryFileServer + , serveDirectoryEmbedded + , serveDirectoryWith + ) where -import Network.Wai.Application.Static (defaultFileServerSettings, - staticApp) +import Data.ByteString (ByteString) +import Network.Wai.Application.Static import Servant.API.Raw (Raw) import Servant.Server (Server) import System.FilePath (addTrailingPathSeparator) #if !MIN_VERSION_wai_app_static(3,1,0) import Filesystem.Path.CurrentOS (decodeString) #endif +import WaiAppStatic.Storage.Filesystem (ETagLookup) -- | Serve anything under the specified directory as a 'Raw' endpoint. -- @@ -22,7 +29,7 @@ import Filesystem.Path.CurrentOS (decodeString) -- type MyApi = "static" :> Raw -- -- server :: Server MyApi --- server = serveDirectory "\/var\/www" +-- server = serveDirectoryWebApp "\/var\/www" -- @ -- -- would capture any request to @\/static\/\@ and look for @@ -33,13 +40,38 @@ import Filesystem.Path.CurrentOS (decodeString) -- -- If your goal is to serve HTML, CSS and Javascript files that use the rest of the API -- as a webapp backend, you will most likely not want the static files to be hidden --- behind a /\/static\// prefix. In that case, remember to put the 'serveDirectory' +-- behind a /\/static\// prefix. In that case, remember to put the 'serveDirectoryWebApp' -- handler in the last position, because /servant/ will try to match the handlers -- in order. -serveDirectory :: FilePath -> Server Raw -serveDirectory = +-- +-- Corresponds to the `defaultWebAppSettings` `StaticSettings` value. +serveDirectoryWebApp :: FilePath -> Server Raw +serveDirectoryWebApp = staticApp . defaultWebAppSettings . fixPath + +-- | Same as 'serveDirectoryWebApp', but uses `defaultFileServerSettings`. +serveDirectoryFileServer :: FilePath -> Server Raw +serveDirectoryFileServer = staticApp . defaultFileServerSettings . fixPath + +-- | Same as 'serveDirectoryWebApp', but uses 'webAppSettingsWithLookup'. +serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> Server Raw +serveDirectoryWebAppLookup etag = + staticApp . flip webAppSettingsWithLookup etag . fixPath + +-- | Uses 'embeddedSettings'. +serveDirectoryEmbedded :: [(FilePath, ByteString)] -> Server Raw +serveDirectoryEmbedded files = staticApp (embeddedSettings files) + +-- | Alias for 'staticApp'. Lets you serve a directory +-- with arbitrary 'StaticSettings'. Useful when you want +-- particular settings not covered by the four other +-- variants. This is the most flexible method. +serveDirectoryWith :: StaticSettings -> Server Raw +serveDirectoryWith = staticApp + +fixPath :: FilePath -> FilePath +fixPath = #if MIN_VERSION_wai_app_static(3,1,0) - staticApp . defaultFileServerSettings . addTrailingPathSeparator + addTrailingPathSeparator #else - staticApp . defaultFileServerSettings . decodeString . addTrailingPathSeparator + decodeString . addTrailingPathSeparator #endif