Failure / Alternative / MonadPlus semantics: a Snap handler can
choose not to handle a given request, using empty or its synonym pass, and
you can try alternative handlers with the <|> operator:
a :: Snap String
a = pass
b :: Snap String
b = return "foo"
c :: Snap String
c = a <|> b -- try running a, if it fails then try b
You may notice that most of the type signatures in this module contain a
(MonadSnap m) => ... typeclass constraint. MonadSnap is a typeclass
which, in essence, says "you can get back to the Snap monad from
here". Using MonadSnap you can extend the Snap monad with additional
functionality and still have access to most of the Snap functions without
writing lift everywhere. Instances are already
provided for most of the common monad transformers
(ReaderT, Control.Monad.Trans.Writer.WriterT,
StateT, etc.).
Pass the request body stream to a consuming procedure, returning the
result.
If the consuming procedure you pass in here throws an exception, Snap will
attempt to clear the rest of the unread request body (using
skipToEof) before rethrowing the
exception. If you used terminateConnection, however, Snap will give up and
immediately close the socket.
To prevent slowloris attacks, the connection will be also terminated if the
input socket produces data too slowly (500 bytes per second is the default
limit).
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.ByteString.Char8 as B8
ghci> import qualified Data.ByteString.Lazy as L
ghci> import Data.Char (toUpper)
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified System.IO.Streams as Streams
ghci> let r = T.put "/foo" "text/plain" "some text"
ghci> :{
ghci| let f s = do u <- Streams.map (B8.map toUpper) s
ghci| l <- Streams.toList u
ghci| return $ L.fromChunks l
ghci| :}
ghci> T.runHandler r (runRequestBody f >>= writeLBS)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 20:48:40 GMT
SOME TEXT
size of the largest request body we're willing
to accept. If a request body longer than this is
received, a TooManyBytesReadException is
thrown. See takeNoMoreThan.
Returns the request body as a lazy bytestring. /Note that the request is
not actually provided lazily!/
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.put "/foo" "text/plain" "some text"
ghci> T.runHandler r (readRequestBody 2048 >>= writeLBS)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 20:08:44 GMT
some text
Normally Snap is careful to ensure that the request body is fully
consumed after your web handler runs, but before the Response body
is streamed out the socket. If you want to transform the request body into
some output in O(1) space, you should use this function.
Take care: in order for this to work, the HTTP client must be written with
input-to-output streaming in mind.
Note that upon calling this function, response processing finishes early as
if you called finishWith. Make sure you set any content types, headers,
cookies, etc. before you call this function.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.ByteString.Char8 as B8
ghci> import Data.Char (toUpper)
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified System.IO.Streams as Streams
ghci> let r = T.put "/foo" "text/plain" "some text"
ghci> let f = Streams.map (B8.map toUpper)
ghci> T.runHandler r (transformRequestBody f >> readRequestBody 2048 >>= writeLBS)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 20:30:15 GMT
SOME TEXT
Short-circuits a Snap monad action early, storing the given
Response value in its state.
IMPORTANT: Be vary careful when using this with things like a DB library's
withTransaction function or any other kind of setup/teardown block, as it
can prevent the cleanup from being called and result in resource leaks.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import Control.Applicative
ghci> let r = T.get "/" M.empty
ghci> T.runHandler r ((ifTop $ writeBS "TOP") <|> finishWithemptyResponse)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 16:58:57 GMT
TOP
ghci> let r' = T.get "/foo/bar" M.empty
ghci> T.runHandler r' ((ifTop $ writeBS "TOP") <|> finishWithemptyResponse)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 17:50:50 GMT
Capture the flow of control in case a handler calls finishWith.
WARNING: in the event of a call to transformRequestBody it is possible
to violate HTTP protocol safety when using this function. If you call
catchFinishWith it is suggested that you do not modify the body of the
Response which was passed to the finishWith call.
Runs a Snap monad action only if the request's HTTP method matches
the given method.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (methodGET $ writeBS "OK")
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 13:38:48 GMT
OK
ghci> T.runHandler r (methodPOST $ writeBS "OK")
HTTP/1.1 404 Not Found
...
Runs a Snap monad action only if the request's HTTP method matches
one of the given methods.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (methods [GET, POST] $ writeBS "OK")
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 13:38:48 GMT
OK
ghci> T.runHandler r (methods [POST] $ writeBS "OK")
HTTP/1.1 404 Not Found
...
Runs a Snap monad action only when the rqPathInfo of the request
starts with the given path. For example,
dir "foo" handler
Will fail if rqPathInfo is not "/foo" or "/foo/...", and will
add "foo/" to the handler's local rqContextPath.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (dir "foo" $ writeBS "OK")
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 14:52:24 GMT
OK
ghci> T.runHandler r (dir "baz" $ writeBS "OK")
HTTP/1.1 404 Not Found
...
Runs a Snap monad action only for requests where rqPathInfo is
exactly equal to the given string. If the path matches, locally sets
rqContextPath to the old value of rqPathInfo, sets rqPathInfo="",
and runs the given handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> T.runHandler (T.get "/foo" M.empty) (path "foo" $ writeBS "bar")
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 14:15:42 GMT
bar
ghci> T.runHandler (T.get "/foo" M.empty) (path "bar" $ writeBS "baz")
HTTP/1.1 404 Not Found
...
Runs a Snap monad action only when the first path component is
successfully parsed as the argument to the supplied handler function.
Note that the path segment is url-decoded prior to being passed to fromBS;
this is new as of snap-core 0.10.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/11/foo/bar" M.empty
ghci> let f = (\i -> if i == 11 then writeBS "11" else writeBS "???")
ghci> T.runHandler r (pathArg f)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 14:27:10 GMT
11
ghci> let r' = T.get "/foo/11/bar" M.empty
ghci> T.runHandler r' (pathArg f)
HTTP/1.1 404 Not Found
...
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/" M.empty
ghci> T.runHandler r (ifTop $ writeBSOK)
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 14:56:39 GMT
OK
ghci> let r' = T.get "/foo" M.empty
ghci> T.runHandler r' (ifTop $ writeBS "OK")
HTTP/1.1 404 Not Found
...
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBS . rqURI =<< getRequest)
HTTP/1.1 200 OK
server: Snap/test
date: Sat, 02 Aug 2014 07:51:54 GMT
/foo/bar
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBS . rspStatusReason =<< getResponse)
HTTP/1.1 200 OK
server: Snap/test
date: Sat, 02 Aug 2014 15:06:00 GMT
OK
Grabs something out of the Request object, using the given projection
function. See gets.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBS =<< getsRequestrqURI)
HTTP/1.1 200 OK
server: Snap/test
date: Sat, 02 Aug 2014 07:51:54 GMT
/foo/bar
Grabs something out of the Response object, using the given projection
function. See gets.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBS =<< getsResponserspStatusReason)
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 13:35:45 GMT
OK
Modifes the Response object stored in a Snap monad.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (modifyResponse $ setResponseCode 404)
HTTP/1.1 404 Not Found
server: Snap/test
date: Wed, 06 Aug 2014 15:27:11 GMT
Performs a redirect by setting the Location header to the given target
URL/path and the status code to 302 in the Response object stored in a
Snap monad. Note that the target URL is not validated in any way.
Consider using redirect' instead, which allows you to choose the correct
status code.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (redirect "http://snapframework.com")
HTTP/1.1 302 Found
content-length: 0
location: http://snapframework.com
server: Snap/test
date: Thu, 07 Aug 2014 08:52:11 GMT
Content-Length: 0
Performs a redirect by setting the Location header to the given target
URL/path and the status code (should be one of 301, 302, 303 or 307) in the
Response object stored in a Snap monad. Note that the target URL is not
validated in any way.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (redirect' "http://snapframework.com" 301)
HTTP/1.1 307 Temporary Redirect
content-length: 0
location: http://snapframework.com
server: Snap/test
date: Thu, 07 Aug 2014 08:55:51 GMT
Content-Length: 0
Run the given stream procedure, adding its output to the Response stored
in the Snap monad state.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified Data.ByteString.Builder as B
ghci> import qualified System.IO.Streams as Streams
ghci> let r = T.get "/foo/bar" M.empty
ghci> :{
ghci| let f str = do {
ghci| Streams.write (Just $ B.byteString "Hello, streams world") str;
ghci| return str }
ghci| :}
ghci> T.runHandler r (addToOutput f)
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:55:47 GMT
Hello, streams world
Adds the given Builder to the body of the Response stored in the
| Snap monad state.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified Data.ByteString.Builder as B
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBuilder $ B.byteString "Hello, world")
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:33:33 GMT
Hello, world
Adds the given strict ByteString to the body of the Response stored
in the Snap monad state.
Warning: This function is intentionally non-strict. If any pure
exceptions are raised by the expression creating the ByteString,
the exception won't actually be raised within the Snap handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeBS "Hello, bytestring world")
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:34:27 GMT
Hello, bytestring world
Adds the given lazy ByteString to the body of the Response stored
in the Snap monad state.
Warning: This function is intentionally non-strict. If any pure
exceptions are raised by the expression creating the ByteString,
the exception won't actually be raised within the Snap handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeLBS "Hello, lazy bytestring world")
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:35:15 GMT
Hello, lazy bytestring world
Adds the given strict Text to the body of the Response stored in
the Snap monad state.
Warning: This function is intentionally non-strict. If any pure
exceptions are raised by the expression creating the ByteString,
the exception won't actually be raised within the Snap handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeText "Hello, text world")
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:36:38 GMT
Hello, text world
Adds the given lazy Text to the body of the Response stored in the
Snap monad state.
Warning: This function is intentionally non-strict. If any pure
exceptions are raised by the expression creating the ByteString,
the exception won't actually be raised within the Snap handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (writeLazyText "Hello, lazy text world")
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 17:37:41 GMT
Hello, lazy text world
Sets the output to be the contents of the specified file.
Calling sendFile will overwrite any output queued to be sent in the
Response. If the response body is not modified after the call to
sendFile, Snap will use the efficient sendfile() system call on
platforms that support it.
If the response body is modified (using modifyResponseBody), the file
will be read using mmap().
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> writeFile "/tmp/snap-file" "Hello, sendFile world"
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (sendFile "/tmp/snap-file")
HTTP/1.1 200 OK
content-length: 21
server: Snap/test
date: Wed, 06 Aug 2014 17:45:10 GMT
Content-Length: 21
Hello, sendFile world
Sets the output to be the contents of the specified file, within the
given (start,end) range.
Calling sendFilePartial will overwrite any output queued to be sent in
the Response. If the response body is not modified after the call to
sendFilePartial, Snap will use the efficient sendfile() system call on
platforms that support it.
If the response body is modified (using modifyResponseBody), the file
will be read using mmap().
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> writeFile "/tmp/snap-file" "Hello, sendFilePartial world"
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (sendFilePartial "/tmp/snap-file" (7, 28))
HTTP/1.1 200 OK
content-length: 21
server: Snap/test
date: Wed, 06 Aug 2014 17:47:20 GMT
Content-Length: 21
sendFilePartial world
Runs a Snap action with a locally-modified Request state
object. The Request object in the Snap monad state after the call
to localRequest will be unchanged.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> r' <- T.buildRequest $ T.get "/bar/foo" M.empty
ghci> let printRqURI = getsRequestrqURI >>= writeBS >> writeBS "\n"
ghci> T.runHandler r (printRqURI >> localRequest (const r') printRqURI)
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 15:34:12 GMT
/foo/bar
/bar/foo
Fetches the Request from state and hands it to the given action.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import Control.Monad.IO.Class
ghci> let r = T.get "/foo/bar" M.empty
ghci> let h = withRequest (\rq -> liftIO (T.requestToString rq) >>= writeBS)
ghci> T.runHandler r h
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 15:44:24 GMT
GET /foo/bar HTTP/1.1
host: localhost
Fetches the Response from state and hands it to the given action.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (withResponse $ writeBS . rspStatusReason)
HTTP/1.1 200 OK
server: Snap/test
date: Wed, 06 Aug 2014 15:48:45 GMT
OK
Modifies the Request in the state to set the rqRemoteAddr
field to the value in the X-Forwarded-For header. If the header is
not present, this action has no effect.
This action should be used only when working behind a reverse http
proxy that sets the X-Forwarded-For header. This is the only way to
ensure the value in the X-Forwarded-For header can be trusted.
This is provided as a filter so actions that require the remote
address can get it in a uniform manner. It has specifically limited
functionality to ensure that its transformation can be trusted,
when used correctly.
Modifies the Request in the state to set the rqRemoteAddr
field to the value from the header specified. If the header
specified is not present, this action has no effect.
This action should be used only when working behind a reverse http
proxy that sets the header being looked at. This is the only way to
ensure the value in the header can be trusted.
This is provided as a filter so actions that require the remote
address can get it in a uniform manner. It has specifically limited
functionality to ensure that its transformation can be trusted,
when used correctly.
This function brackets a Snap action in resource acquisition and
release. This is provided because MonadCatchIO's bracket function
doesn't work properly in the case of a short-circuit return from
the action being bracketed.
In order to prevent confusion regarding the effects of the
aquisition and release actions on the Snap state, this function
doesn't accept Snap actions for the acquire or release actions.
This function will run the release action in all cases where the
acquire action succeeded. This includes the following behaviors
from the bracketed Snap action.
Normal completion
Short-circuit completion, either from calling fail or finishWith
An exception being thrown.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> let br = bracketSnap (putStrLn "before") (const $ putStrLn "after")
ghci> T.runHandler (T.get "/" M.empty) (br $ const $ writeBS "OK")
before
after
HTTP/1.1 200 OK
server: Snap/test
date: Thu, 07 Aug 2014 18:41:50 GMT
OK
Terminate the HTTP session with the given exception.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Data.Map as M
ghci> import qualified Snap.Test as T
ghci> import qualified Control.Exception as E
ghci> let r = T.get "/foo/bar" M.empty
ghci> T.runHandler r (terminateConnection $ E.AssertionFailed "Assertion failed!")
*** Exception: <terminated: Assertion failed!>
This function is mostly intended for library writers; instead of invoking
runSnap directly, use Snap.Http.Server.httpServe or
runHandler (for testing).
Unlike runSnap, evalSnap evaluates to the value, not the Response.
Like runSnap, evalSnap is intended for library writers.
Note that there is no meaningful way of evaluating a Snap monad action
that contains pass without alternative (i.e. failure), finishWith
(i.e. early termination), or escapeHttp (i.e. escaping Snap).
In all of those three cases evalSnap throws an IO exception.
See rqParam. Looks up a value for the given named parameter in the
Request. If more than one value was entered for the given parameter name,
getParam gloms the values together with intercalate " ".
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> let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])]
ghci> T.runHandler r (getParam "foo" >>= writeBS . B8.pack . show)
HTTP/1.1 200 OK
server: Snap/test
date: Mon, 11 Aug 2014 12:57:20 GMT
Just "bar"
See rqPostParam. Looks up a value for the given named parameter in the
POST form parameters mapping in Request. If more than one value was
entered for the given parameter name, getPostParam gloms the values
together with: intercalate " ".
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> let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])]
ghci> T.runHandler r (getPostParam "foo" >>= writeBS . B8.pack . show)
HTTP/1.1 200 OK
server: Snap/test
date: Mon, 11 Aug 2014 13:01:04 GMT
Just "bar"
See rqQueryParam. Looks up a value for the given named parameter in the
query string parameters mapping in Request. If more than one value was
entered for the given parameter name, getQueryParam gloms the values
together with intercalate " ".
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> let r = T.postUrlEncoded "/foo/bar" M.empty >> T.setQueryStringRaw "foo=bar&foo=baz"
ghci> T.runHandler r (getQueryParam "foo" >>= writeBS . B8.pack . show)
HTTP/1.1 200 OK
server: Snap/test
date: Mon, 11 Aug 2014 13:06:50 GMT
Just "bar baz"
Returns the port number the HTTP server is listening on. This may be
useless from the perspective of external requests, e.g. if the server
is running behind a proxy.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> rqServerPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
8080
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> rqMethod `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
GET
Handlers can be hung on a URI "entry point"; this is called the
"context path". If a handler is hung on the context path
"/foo/", and you request "/foo/bar", the value of
rqPathInfo will be "bar".
The following identity holds:
rqURI r == S.concat [ rqContextPath r
, rqPathInfo r
, let q = rqQueryString r
in if S.null q
then ""
else S.append "?" q
]
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> rqPathInfo `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
"foo/bar"
The "context path" of the request; catenating rqContextPath,
and rqPathInfo should get you back to the original rqURI
(ignoring query strings). The rqContextPath always begins and ends
with a slash ("/") character, and represents the path (relative
to your component/snaplet) you took to get to your handler.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> rqContextPath `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
"/"
Returns the parameters mapping for this Request. "Parameters"
are automatically decoded from the URI's query string and POST body
and entered into this mapping. The rqParams value is thus a union of
rqQueryParams and rqPostParams.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> :{
ghci| rq <- T.buildRequest $ do
ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
ghci| T.setQueryStringRaw "baz=quux"
ghci| :}
ghci> rqParams rq
fromList [("baz",["qux","quux"])]
The parameter mapping decoded from the POST body. Note that Snap
only auto-decodes POST request bodies when the request's
Content-Type is application/x-www-form-urlencoded.
For multipart/form-data use handleFileUploads
to decode the POST request and fill this mapping.
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> :{
ghci| rq <- T.buildRequest $ do
ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
ghci| T.setQueryStringRaw "baz=quux"
ghci| :}
ghci> rqPostParams rq
fromList [("baz",["qux"])]
Instances3Show, HasHeaders, MonadState
ShowRequestDefined in snap-core-1.0.5.1 · Snap.Internal.Http.Types
HasHeadersRequestDefined in snap-core-1.0.5.1 · Snap.Internal.Http.Types
We will need to inspect the content length no matter what, and
looking up "content-length" in the headers and parsing the number
out of the text will be too expensive.
A type alias for the HTTP parameters mapping. Each parameter
key maps to a list of ByteString values; if a parameter is specified
multiple times (e.g.: "GET /foo?param=bar1¶m=bar2"), looking up
"param" in the mapping will give you ["bar1", "bar2"].
Adds a header key-value-pair to the HasHeaders datatype. If a header
with the same name already exists, the new value is appended to the headers
list.
Example:
ghci> import qualified Snap.Types.Headers as H
ghci> addHeader "Host" "localhost" H.empty
H {unH = [("host","localhost")]}
ghci> addHeader "Host" "127.0.0.1" it
H {unH = [("host","localhost,127.0.0.1")]}
Sets a header key-value-pair in a HasHeaders datatype. If a header with
the same name already exists, it is overwritten with the new value.
Example:
ghci> import qualified Snap.Types.Headers as H
ghci> setHeader "Host" "localhost" H.empty
H {unH = [("host","localhost")]}
ghci> setHeader "Host" "127.0.0.1" it
H {unH = [("host","127.0.0.1")]}
Looks up the value(s) for the given named parameter. Parameters initially
come from the request's query string and any decoded POST body (if the
request's Content-Type is application/x-www-form-urlencoded).
Parameter values can be modified within handlers using "rqModifyParams".
Example:
ghci> :set -XOverloadedStrings
ghci> import qualified Snap.Test as T
ghci> import qualified Data.Map as M
ghci> :{
ghci| rq <- T.buildRequest $ do
ghci| T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
ghci| T.setQueryStringRaw "baz=quux"
ghci| :}
ghci> rqParam "baz" rq
Just ["qux","quux"]
A note here: if you want to set the Content-Length for the response,
Snap forces you to do it with this function rather than by setting it in
the headers; the Content-Length in the headers will be ignored.
The reason for this is that Snap needs to look up the value of
Content-Length for each request, and looking the string value up in the
headers and parsing the number out of the text will be too expensive.
If you don't set a content length in your response, HTTP keep-alive will be
disabled for HTTP/1.0 clients, forcing a Connection: close. For
HTTP/1.1 clients, Snap will switch to the chunked transfer encoding if
Content-Length is not specified.
Example:
ghci> setContentLength 400 emptyResponse
HTTP/1.1 200 OK
Content-Length: 400