-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Snap: A Haskell Web Framework (core interfaces and types)
--   
--   Snap is a simple and fast web development framework and server written
--   in Haskell. For more information or to download the latest version,
--   you can visit the Snap project website at
--   <a>http://snapframework.com/</a>.
--   
--   This library contains the core definitions and types for the Snap
--   framework, including:
--   
--   <ol>
--   <li>Primitive types and functions for HTTP (requests, responses,
--   cookies, post/query parameters, etc)</li>
--   <li>A monad for programming web handlers called "Snap", which
--   allows:</li>
--   </ol>
--   
--   <ul>
--   <li>Stateful access to the HTTP request and response objects</li>
--   <li>Monadic failure (i.e. MonadPlus/Alternative instances) for
--   declining to handle requests and chaining handlers together</li>
--   <li>Early termination of the computation if you know early what you
--   want to return and want to prevent further monadic processing</li>
--   </ul>
--   
--   <i>Quick start</i>: The <a>Snap</a> monad and HTTP definitions are in
--   <a>Snap.Core</a>.
@package snap-core
@version 1.0.5.0


-- | An internal Snap module for (optionally) printing debugging messages.
--   To enable debug output, compile the library with the <tt>debug</tt>
--   flag (off by default) and set the environment variable <tt>DEBUG</tt>
--   to <tt>1</tt>. We use <tt>unsafePerformIO</tt> to make sure that the
--   call to <tt>getEnv</tt> is only made once.
--   
--   <i>N.B.</i> this is an internal interface, please don't write external
--   code that depends on it.
module Snap.Internal.Debug

-- | Print out the provided debug message prefixed by the thread ID.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; debug "Some debug message"
--   [     225] Some debug message
--   </pre>
debug :: MonadIO m => String -> m ()

-- | Print out the error message corresponding to the <a>Errno</a> value
--   returned by <a>getErrno</a> together with any additional information
--   provided by the user (usually the location where the error occurred).
--   
--   Example:
--   
--   <pre>
--   ghci&gt; debugErrno "path<i>to</i>Source.hs:34"
--   [     323] path<i>to</i>Source.hs:34: failed (Success)
--   </pre>
debugErrno :: MonadIO m => String -> m ()


-- | An opaque data type for HTTP headers. Intended to be imported
--   qualified, i.e:
--   
--   <pre>
--   import           Snap.Types.Headers (Headers)
--   import qualified Snap.Types.Headers as H
--   
--   foo :: Headers
--   foo = H.empty
--   </pre>
module Snap.Types.Headers

-- | A key-value map that represents a collection of HTTP header fields.
--   Keys are case-insensitive.
data Headers

-- | An empty collection of HTTP header fields.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; H.<a>empty</a>
--   H {unH = []}
--   </pre>
empty :: Headers

-- | Is a given collection of HTTP header fields empty?
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>null</a> H.<a>empty</a>
--   True
--   ghci&gt; H.<a>null</a> $ H.<a>fromList</a> [("Host", "localhost")]
--   False
--   </pre>
null :: Headers -> Bool

-- | Does this collection of HTTP header fields contain a given field?
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>member</a> "host" $ H.<a>fromList</a> [("Host", "localhost")]
--   True
--   ghci&gt; H.<a>member</a> "Accept" $ H.<a>fromList</a> [("Host", "localhost")]
--   False
--   </pre>
member :: CI ByteString -> Headers -> Bool

-- | Look up the value of a given HTTP header field.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>lookup</a> "host" $ H.<a>fromList</a> [("Host", "localhost")]
--   Just "localhost"
--   ghci&gt; H.<a>lookup</a> "Accept" $ H.<a>fromList</a> [("Host", "localhost")]
--   Nothing
--   </pre>
lookup :: CI ByteString -> Headers -> Maybe ByteString

-- | Look up the value of a given HTTP header field or return the provided
--   default value when that header field is not present.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let hdrs = H.<a>fromList</a> [("Host", "localhost")]
--   ghci&gt; H.<a>lookupWithDefault</a> "host" "127.0.0.1" $ hdrs
--   "localhost"
--   ghci&gt; H.<a>lookupWithDefault</a> "Accept" "text/plain" $ hdrs
--   "text/plain"
--   </pre>
lookupWithDefault :: ByteString -> CI ByteString -> Headers -> ByteString

-- | Insert a key-value pair into the headers map. If the key already
--   exists in the map, the values are catenated with ", ".
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let hdrs = H.<a>insert</a> "Accept" "text/plain" $ H.<a>empty</a>
--   ghci&gt; hdrs
--   H {unH = [("accept","text/plain")]}
--   ghci&gt; H.<a>insert</a> "Accept" "text/html" $ hdrs
--   H {unH = [("accept","text/plain,text/html")]}
--   </pre>
insert :: CI ByteString -> ByteString -> Headers -> Headers

-- | Insert a key-value pair into the headers map, without checking whether
--   the header already exists. The key <i>must</i> be already case-folded,
--   or none of the lookups will work!
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let hdrs = H.<a>unsafeInsert</a> "accept" "text/plain" $ H.<a>empty</a>
--   ghci&gt; hdrs
--   H {unH = [("accept","text/plain")]}
--   ghci&gt; let hdrs' = H.<a>unsafeInsert</a> "accept" "text/html" $ hdrs
--   ghci&gt; hdrs'
--   H {unH = [("accept","text/html"), ("accept","text/plain")]}
--   ghci&gt; H.<a>lookup</a> "accept" hdrs'
--   Just "text/html"
--   </pre>
unsafeInsert :: ByteString -> ByteString -> Headers -> Headers

-- | Set the value of a HTTP header field to a given value, replacing the
--   old value.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>set</a> "accept" "text/plain" $ H.<a>empty</a>
--   H {unH = [("accept","text/plain")]}
--   ghci&gt; H.<a>set</a> "accept" "text/html" $ H.<a>fromList</a> [("Accept", "text/plain")]
--   H {unH = [("accept","text/html")]}
--   </pre>
set :: CI ByteString -> ByteString -> Headers -> Headers

-- | Delete all key-value pairs associated with the given key from the
--   headers map.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>delete</a> "accept" $ H.<a>fromList</a> [("Accept", "text/plain")]
--   H {unH = []}
--   </pre>
delete :: CI ByteString -> Headers -> Headers

-- | Strict left fold over all key-value pairs in the headers map.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; let hdrs = H.<a>fromList</a> [("Accept", "text/plain"), ("Accept", "text/html")]
--   ghci&gt; let f (cntr, acc) _ val = (cntr+1, val &lt;&gt; ";" &lt;&gt; acc)
--   ghci&gt; H.<a>foldl'</a> f (0, "") hdrs
--   (2,"text/html;text/plain;")
--   </pre>
foldl' :: (a -> CI ByteString -> ByteString -> a) -> a -> Headers -> a

-- | Right fold over all key-value pairs in the headers map.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; let hdrs = H.<a>fromList</a> [("Accept", "text/plain"), ("Accept", "text/html")]
--   ghci&gt; let f _ val (cntr, acc) = (cntr+1, val &lt;&gt; ";" &lt;&gt; acc)
--   ghci&gt; H.<a>foldr</a> f (0, "") hdrs
--   (2,"text/plain;text/html;")
--   </pre>
foldr :: (CI ByteString -> ByteString -> a -> a) -> a -> Headers -> a

-- | Same as <a>foldl'</a>, but the key parameter is of type
--   <a>ByteString</a> instead of <a>CI</a> <a>ByteString</a>. The key is
--   case-folded (lowercase).
foldedFoldl' :: (a -> ByteString -> ByteString -> a) -> a -> Headers -> a

-- | Same as <a>foldr</a>, but the key parameter is of type
--   <a>ByteString</a> instead of <a>CI</a> <a>ByteString</a>. The key is
--   case-folded (lowercase).
foldedFoldr :: (ByteString -> ByteString -> a -> a) -> a -> Headers -> a

-- | Convert a <a>Headers</a> value to a list of key-value pairs.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let l = [("Accept", "text/plain"), ("Accept", "text/html")]
--   ghci&gt; H.<a>toList</a> . H.<a>fromList</a> $ l
--   [("accept","text/plain"),("accept","text/html")]
--   </pre>
toList :: Headers -> [(CI ByteString, ByteString)]

-- | Build a <a>Headers</a> value from a list of key-value pairs.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; H.<a>fromList</a> [("Accept", "text/plain"), ("Accept", "text/html")]
--   H {unH = [("accept","text/plain"),("accept","text/html")]}
--   </pre>
fromList :: [(CI ByteString, ByteString)] -> Headers

-- | Like <a>fromList</a>, but the keys are assumed to be already
--   case-folded (in lowercase).
unsafeFromCaseFoldedList :: [(ByteString, ByteString)] -> Headers

-- | Like <a>toList</a>, but does not convert the keys to <a>CI</a>
--   <a>ByteString</a>, so key comparisons will be case-sensitive.
unsafeToCaseFoldedList :: Headers -> [(ByteString, ByteString)]
instance GHC.Show.Show Snap.Types.Headers.Headers


-- | An internal Snap module containing HTTP types.
--   
--   <i>N.B.</i> this is an internal interface, please don't write user
--   code that depends on it. Most of these declarations (except for the
--   unsafe/encapsulation-breaking ones) are re-exported from
--   <a>Snap.Core</a>.
module Snap.Internal.Http.Types

-- | A typeclass for datatypes which contain HTTP headers.
class HasHeaders a

-- | Modify the datatype's headers.
updateHeaders :: HasHeaders a => (Headers -> Headers) -> a -> a

-- | Retrieve the headers from a datatype that has headers.
headers :: HasHeaders a => a -> Headers

-- | Adds a header key-value-pair to the <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, the new value is appended to
--   the headers list.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>addHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; <a>addHeader</a> "Host" "127.0.0.1" it
--   H {unH = [("host","localhost,127.0.0.1")]}
--   </pre>
addHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Sets a header key-value-pair in a <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, it is overwritten with the
--   new value.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; setHeader "Host" "127.0.0.1" it
--   H {unH = [("host","127.0.0.1")]}
--   </pre>
setHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Gets a header value out of a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>getHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   Just "localhost"
--   </pre>
getHeader :: HasHeaders a => CI ByteString -> a -> Maybe ByteString

-- | Lists all the headers out of a <a>HasHeaders</a> datatype. If many
--   headers came in with the same name, they will be catenated together.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>listHeaders</a> $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   [("host","localhost")]
--   </pre>
listHeaders :: HasHeaders a => a -> [(CI ByteString, ByteString)]

-- | Clears a header value from a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>deleteHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = []}
--   </pre>
deleteHeader :: HasHeaders a => CI ByteString -> a -> a

-- | Enumerates the HTTP method values (see
--   <a>http://tools.ietf.org/html/rfc2068.html#section-5.1.1</a>).
data Method
GET :: Method
HEAD :: Method
POST :: Method
PUT :: Method
DELETE :: Method
TRACE :: Method
OPTIONS :: Method
CONNECT :: Method
PATCH :: Method
Method :: ByteString -> Method

-- | Equate the special case constructors with their corresponding
--   <tt>Method name</tt> variant.
normalizeMethod :: Method -> Method

-- | Represents a (major, minor) version of the HTTP protocol.
type HttpVersion = (Int, Int)

-- | A datatype representing an HTTP cookie.
data Cookie
Cookie :: !ByteString -> !ByteString -> !Maybe UTCTime -> !Maybe ByteString -> !Maybe ByteString -> !Bool -> !Bool -> Cookie

-- | The name of the cookie.
[cookieName] :: Cookie -> !ByteString

-- | The cookie's string value.
[cookieValue] :: Cookie -> !ByteString

-- | The cookie's expiration value, if it has one.
[cookieExpires] :: Cookie -> !Maybe UTCTime

-- | The cookie's "domain" value, if it has one.
[cookieDomain] :: Cookie -> !Maybe ByteString

-- | The cookie path.
[cookiePath] :: Cookie -> !Maybe ByteString

-- | Tag as secure cookie?
[cookieSecure] :: Cookie -> !Bool

-- | HTTP only?
[cookieHttpOnly] :: Cookie -> !Bool

-- | A type alias for the HTTP parameters mapping. Each parameter key maps
--   to a list of <a>ByteString</a> values; if a parameter is specified
--   multiple times (e.g.: "<tt>GET /foo?param=bar1&amp;param=bar2</tt>"),
--   looking up "<tt>param</tt>" in the mapping will give you <tt>["bar1",
--   "bar2"]</tt>.
type Params = Map ByteString [ByteString]

-- | Contains all of the information about an incoming HTTP request.
data Request
Request :: ByteString -> ByteString -> {-# UNPACK #-} !Int -> ByteString -> {-# UNPACK #-} !Int -> ByteString -> !Bool -> Headers -> InputStream ByteString -> !Maybe Word64 -> !Method -> {-# UNPACK #-} !HttpVersion -> [Cookie] -> ByteString -> ByteString -> ByteString -> ByteString -> Params -> Params -> Params -> Request

-- | The server name of the request, as it came in from the request's
--   <tt>Host:</tt> header.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.get "/foo/bar" M.empty
--   ghci|         T.setHeader "host" "example.com"
--   ghci| :}
--   ghci&gt; rqHostName rq
--   "example.com"
--   </pre>
[rqHostName] :: Request -> ByteString

-- | The remote IP address.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
[rqClientAddr] :: Request -> ByteString

-- | The remote TCP port number.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "60000"
--   </pre>
[rqClientPort] :: Request -> {-# UNPACK #-} !Int

-- | The local IP address for this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
[rqServerAddr] :: Request -> ByteString

-- | 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   8080
--   </pre>
[rqServerPort] :: Request -> {-# UNPACK #-} !Int

-- | Returns the HTTP server's idea of its local hostname, including port.
--   This is as configured with the <tt>Config</tt> object at startup.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqLocalHostname `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "localhost"
--   </pre>
[rqLocalHostname] :: Request -> ByteString

-- | Returns <tt>True</tt> if this is an HTTPS session.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqIsSecure `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   False
--   </pre>
[rqIsSecure] :: Request -> !Bool

-- | Contains all HTTP <a>Headers</a> associated with this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqHeaders `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   H {unH = [("host","localhost")]}
--   </pre>
[rqHeaders] :: Request -> Headers

-- | Actual body of the request.
[rqBody] :: Request -> InputStream ByteString

-- | Returns the <tt>Content-Length</tt> of the HTTP request body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContentLength `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   Nothing
--   </pre>
[rqContentLength] :: Request -> !Maybe Word64

-- | Returns the HTTP request method.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqMethod `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   GET
--   </pre>
[rqMethod] :: Request -> !Method

-- | Returns the HTTP version used by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqVersion `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   (1,1)
--   </pre>
[rqVersion] :: Request -> {-# UNPACK #-} !HttpVersion

-- | Returns a list of the cookies that came in from the HTTP request
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqCookies `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   []
--   </pre>
[rqCookies] :: Request -> [Cookie]

-- | Handlers can be hung on a <tt>URI</tt> "entry point"; this is called
--   the "context path". If a handler is hung on the context path
--   <tt>"/foo/"</tt>, and you request <tt>"/foo/bar"</tt>, the value of
--   <a>rqPathInfo</a> will be <tt>"bar"</tt>.
--   
--   The following identity holds:
--   
--   <pre>
--   rqURI r == S.concat [ rqContextPath r
--                       , rqPathInfo r
--                       , let q = rqQueryString r
--                         in if S.null q
--                              then ""
--                              else S.append "?" q
--                       ]
--   </pre>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqPathInfo `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
[rqPathInfo] :: Request -> ByteString

-- | The "context path" of the request; catenating <a>rqContextPath</a>,
--   and <a>rqPathInfo</a> should get you back to the original <a>rqURI</a>
--   (ignoring query strings). The <a>rqContextPath</a> always begins and
--   ends with a slash (<tt>"/"</tt>) character, and represents the path
--   (relative to your component/snaplet) you took to get to your handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContextPath `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "/"
--   </pre>
[rqContextPath] :: Request -> ByteString

-- | Returns the <tt>URI</tt> requested by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqURI `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
[rqURI] :: Request -> ByteString

-- | Returns the HTTP query string for this <a>Request</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rq &lt;- T.buildRequest (T.get "/foo/bar" (M.fromList [("name", ["value"])]))
--   ghci&gt; rqQueryString rq
--   "name=value"
--   </pre>
[rqQueryString] :: Request -> ByteString

-- | Returns the parameters mapping for this <a>Request</a>. "Parameters"
--   are automatically decoded from the URI's query string and
--   <tt>POST</tt> body and entered into this mapping. The <a>rqParams</a>
--   value is thus a union of <a>rqQueryParams</a> and <a>rqPostParams</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqParams rq
--   fromList [("baz",["qux","quux"])]
--   </pre>
[rqParams] :: Request -> Params

-- | The parameter mapping decoded from the URI's query string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqQueryParams rq
--   fromList [("baz",["quux"])]
--   </pre>
[rqQueryParams] :: Request -> Params

-- | The parameter mapping decoded from the POST body. Note that Snap only
--   auto-decodes POST request bodies when the request's
--   <tt>Content-Type</tt> is <tt>application/x-www-form-urlencoded</tt>.
--   For <tt>multipart/form-data</tt> use <a>handleFileUploads</a> to
--   decode the POST request and fill this mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqPostParams rq
--   fromList [("baz",["qux"])]
--   </pre>
[rqPostParams] :: Request -> Params
type StreamProc = OutputStream Builder -> IO (OutputStream Builder)
data ResponseBody

-- | output body is a function that writes to a <a>Builder</a> stream
Stream :: StreamProc -> ResponseBody

-- | output body is sendfile(), optional second argument is a byte range to
--   send
SendFile :: FilePath -> Maybe (Word64, Word64) -> ResponseBody
rspBodyMap :: (StreamProc -> StreamProc) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> StreamProc

-- | Represents an HTTP response.
data Response
Response :: Headers -> Map ByteString Cookie -> !Maybe Word64 -> ResponseBody -> !Int -> !ByteString -> !Bool -> Response
[rspHeaders] :: Response -> Headers
[rspCookies] :: Response -> Map ByteString Cookie

-- | 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.
[rspContentLength] :: Response -> !Maybe Word64
[rspBody] :: Response -> ResponseBody

-- | Returns the HTTP status code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatus <a>emptyResponse</a>
--   200
--   </pre>
[rspStatus] :: Response -> !Int

-- | Returns the HTTP status explanation string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatusReason <a>emptyResponse</a>
--   <a>OK</a>
--   </pre>
[rspStatusReason] :: Response -> !ByteString

-- | If true, we are transforming the request body with
--   <tt>transformRequestBody</tt>
[rspTransformingRqBody] :: Response -> !Bool

-- | 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 <tt>Content-Type</tt> is
--   <tt>application/x-www-form-urlencoded</tt>). Parameter values can be
--   modified within handlers using "rqModifyParams".
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParam</a> "baz" rq
--   Just ["qux","quux"]
--   </pre>
rqParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the POST
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqPostParam</a> "baz" rq
--   Just ["qux"]
--   </pre>
rqPostParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the query
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqQueryParam</a> "baz" rq
--   Just ["quux"]
--   </pre>
rqQueryParam :: ByteString -> Request -> Maybe [ByteString]

-- | Modifies the parameters mapping (which is a <tt>Map ByteString
--   ByteString</tt>) in a <a>Request</a> using the given function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqModifyParams</a> (M.delete "baz") rq
--   fromList []
--   </pre>
rqModifyParams :: (Params -> Params) -> Request -> Request

-- | Writes a key-value pair to the parameters mapping within the given
--   request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqSetParam</a> "baz" ["corge"] rq
--   fromList [("baz", ["corge"])]
--   </pre>
rqSetParam :: ByteString -> [ByteString] -> Request -> Request

-- | An empty <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
emptyResponse :: Response

-- | Sets an HTTP response body to the given stream procedure.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   </pre>
setResponseBody :: (OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Sets the HTTP response status. Note: normally you would use
--   <a>setResponseCode</a> unless you needed a custom response
--   explanation.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setResponseStatus 500 "Internal Server Error" <a>emptyResponse</a>
--   HTTP/1.1 500 Internal Server Error
--   </pre>
setResponseStatus :: Int -> ByteString -> Response -> Response

-- | Sets the HTTP response code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setResponseCode 404 <a>emptyResponse</a>
--   HTTP/1.1 404 Not Found
--   </pre>
setResponseCode :: Int -> Response -> Response

-- | Modifies a response body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   ghci&gt; :{
--   ghci| let r' = <a>modifyResponseBody</a>
--   ghci|          (f out -&gt; do
--   ghci|              out' &lt;- f out
--   ghci|              Streams.write (Just $ Builder.<a>byteString</a> "\nBye, world!") out'
--   ghci|              return out') r
--   ghci| :}
--   ghci&gt; r'
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   Bye, world!
--   </pre>
modifyResponseBody :: ((OutputStream Builder -> IO (OutputStream Builder)) -> OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Sets the <tt>Content-Type</tt> in the <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setContentType "text/html" <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   content-type: text/html
--   </pre>
setContentType :: ByteString -> Response -> Response

-- | Convert <a>Cookie</a> into <a>ByteString</a> for output.
--   
--   TODO: Remove duplication. This function is copied from
--   snap-server/Snap.Internal.Http.Server.Session.
cookieToBS :: Cookie -> ByteString

-- | Render cookies from a given <a>Response</a> to <a>Headers</a>.
--   
--   TODO: Remove duplication. This function is copied from
--   snap-server/Snap.Internal.Http.Server.Session.
renderCookies :: Response -> Headers -> Headers

-- | Adds an HTTP <a>Cookie</a> to <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   </pre>
addResponseCookie :: Cookie -> Response -> Response

-- | Gets an HTTP <a>Cookie</a> with the given name from <a>Response</a>
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>getResponseCookie</a> "cookie-name" <a>emptyResponse</a>
--   Nothing
--   </pre>
getResponseCookie :: ByteString -> Response -> Maybe Cookie

-- | Returns a list of <a>Cookie</a>s present in <a>Response</a>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>getResponseCookies</a> <a>emptyResponse</a>
--   []
--   </pre>
getResponseCookies :: Response -> [Cookie]

-- | Deletes an HTTP <a>Cookie</a> from the <a>Response</a> headers. Please
--   note this does not necessarily erase the cookie from the client
--   browser.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>deleteResponseCookie</a> "name" rsp
--   Nothing
--   </pre>
deleteResponseCookie :: ByteString -> Response -> Response

-- | Modifies an HTTP <a>Cookie</a> with given name in <a>Response</a>
--   headers. Nothing will happen if a matching <a>Cookie</a> can not be
--   found in <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; let f ck@(<a>Cookie</a> { cookieName = name }) = ck { cookieName = name &lt;&gt; "'"}
--   ghci&gt; let rsp' = <a>modifyResponseCookie</a> "name" f rsp
--   ghci&gt; <a>getResponseCookie</a> "name'" rsp'
--   Just (Cookie {cookieName = "name'", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" rsp'
--   Just (Cookie {cookieName = "name", ...})
--   </pre>
modifyResponseCookie :: ByteString -> (Cookie -> Cookie) -> Response -> Response

-- | A note here: if you want to set the <tt>Content-Length</tt> for the
--   response, Snap forces you to do it with this function rather than by
--   setting it in the headers; the <tt>Content-Length</tt> in the headers
--   will be ignored.
--   
--   The reason for this is that Snap needs to look up the value of
--   <tt>Content-Length</tt> 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 <tt>Connection:
--   close</tt>. For HTTP/1.1 clients, Snap will switch to the chunked
--   transfer encoding if <tt>Content-Length</tt> is not specified.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setContentLength 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   Content-Length: 400
--   </pre>
setContentLength :: Word64 -> Response -> Response

-- | Removes any <tt>Content-Length</tt> set in the <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; clearContentLength $ <a>setContentLength</a> 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
clearContentLength :: Response -> Response

-- | Convert a <a>CTime</a> into an HTTP timestamp.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>formatHttpTime</a> . <a>fromIntegral</a> $ 10
--   "Thu, 01 Jan 1970 00:00:10 GMT"
--   </pre>
formatHttpTime :: CTime -> IO ByteString

-- | Convert a <a>CTime</a> into common log entry format.
formatLogTime :: CTime -> IO ByteString

-- | Converts an HTTP timestamp into a <a>CTime</a>.
--   
--   If the given time string is unparseable, this function will return 0.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>parseHttpTime</a> "Thu, 01 Jan 1970 00:00:10 GMT"
--   10
--   </pre>
parseHttpTime :: ByteString -> IO CTime
fromStr :: String -> ByteString

-- | Adapted from:
--   
--   
--   <a>https://www.iana.org/assignments/http-status-codes/http-status-codes.txt</a>
statusReasonMap :: IntMap ByteString

-- | See <a>rqClientAddr</a>.

-- | <i>Deprecated: (snap-core &gt;= 1.0.0.0) please use
--   <a>rqClientAddr</a>, this will be removed in 1.1.*</i>
rqRemoteAddr :: Request -> ByteString

-- | See <a>rqClientPort</a>.

-- | <i>Deprecated: (snap-core &gt;= 1.0.0.0) please use
--   <a>rqClientPort</a>, this will be removed in 1.1.*</i>
rqRemotePort :: Request -> Int
instance GHC.Read.Read Snap.Internal.Http.Types.Method
instance GHC.Show.Show Snap.Internal.Http.Types.Method
instance GHC.Show.Show Snap.Internal.Http.Types.Cookie
instance GHC.Classes.Eq Snap.Internal.Http.Types.Cookie
instance GHC.Show.Show Snap.Internal.Http.Types.Response
instance Snap.Internal.Http.Types.HasHeaders Snap.Internal.Http.Types.Response
instance GHC.Show.Show Snap.Internal.Http.Types.Request
instance Snap.Internal.Http.Types.HasHeaders Snap.Internal.Http.Types.Request
instance GHC.Classes.Eq Snap.Internal.Http.Types.Method
instance GHC.Classes.Ord Snap.Internal.Http.Types.Method
instance Snap.Internal.Http.Types.HasHeaders Snap.Types.Headers.Headers

module Snap.Internal.Parsing
fullyParse :: ByteString -> Parser a -> Either String a
(<?>) :: Parser a -> String -> Parser a
infix 0 <?>
fullyParse' :: (Parser a -> ByteString -> Result a) -> (Result a -> ByteString -> Result a) -> ByteString -> Parser a -> Either String a
parseNum :: Parser Int64
untilEOL :: Parser ByteString
crlf :: Parser ByteString
toTableList :: (Char -> Bool) -> [Char]
toTable :: (Char -> Bool) -> Char -> Bool
skipFieldChars :: Parser ()
isFieldChar :: Char -> Bool

-- | Parser for request headers.
pHeaders :: Parser [(ByteString, ByteString)]
pWord :: Parser ByteString
pWord' :: (Char -> Bool) -> Parser ByteString
pQuotedString :: Parser ByteString
pQuotedString' :: (Char -> Bool) -> Parser ByteString
isRFCText :: Char -> Bool
matchAll :: [Char -> Bool] -> Char -> Bool
pAvPairs :: Parser [(ByteString, ByteString)]
pAvPair :: Parser (ByteString, ByteString)
pParameter :: Parser (ByteString, ByteString)
pParameter' :: (Char -> Bool) -> Parser (ByteString, ByteString)
trim :: ByteString -> ByteString
pValueWithParameters :: Parser (ByteString, [(CI ByteString, ByteString)])
pValueWithParameters' :: (Char -> Bool) -> Parser (ByteString, [(CI ByteString, ByteString)])
pContentTypeWithParameters :: Parser (ByteString, [(CI ByteString, ByteString)])
pToken :: Parser ByteString
isToken :: Char -> Bool

-- | Used for "#field-name", and field-name = token, so "#token":
--   comma-separated tokens/field-names, like a header field list.
pTokens :: Parser [ByteString]
parseToCompletion :: Parser a -> ByteString -> Maybe a
type DList a = [a] -> [a]
pUrlEscaped :: Parser ByteString

-- | Decode an URL-escaped string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>)
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>urlDecode</a> "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   Just "1 attoparsec ~= 3 * 10^-2 meters"
--   </pre>
urlDecode :: ByteString -> Maybe ByteString

-- | URL-escape a string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>)
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>urlEncode</a> "1 attoparsec ~= 3 * 10^-2 meters"
--   "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   </pre>
urlEncode :: ByteString -> ByteString

-- | URL-escape a string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>) into a
--   <a>Builder</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import <a>Data.ByteString.Builder</a>
--   ghci&gt; <a>toLazyByteString</a> . <a>urlEncodeBuilder</a> $ "1 attoparsec ~= 3 * 10^-2 meters"
--   "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   </pre>
urlEncodeBuilder :: ByteString -> Builder
urlEncodeClean :: Char -> Bool
hexd :: Char -> Builder
finish :: Result a -> Result a

-- | Parse a string encoded in <tt>application/x-www-form-urlencoded</tt>
--   <a>format</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>parseUrlEncoded</a> "Name=John+Doe&amp;Name=Jane+Doe&amp;Age=23&amp;Formula=a+%2B+b+%3D%3D+13%25%21"
--   <a>fromList</a> [(<a>Age</a>,["23"]),(<a>Formula</a>,["a + b == 13%!"]),(<a>Name</a>,["John Doe","Jane Doe"])]
--   </pre>
parseUrlEncoded :: ByteString -> Map ByteString [ByteString]

-- | Like <a>printUrlEncoded</a>, but produces a <a>Builder</a> instead of
--   a <a>ByteString</a>. Useful for constructing a large string
--   efficiently in a single step.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import <a>Data.Map</a>
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; import <a>Data.ByteString.Builder</a>
--   ghci&gt; let bldr = <a>buildUrlEncoded</a> (<a>fromList</a> [(<a>Name</a>, ["John Doe"]), (<a>Age</a>, ["23"])])
--   ghci&gt; <a>toLazyByteString</a> $ <a>byteString</a> "<a>http://example.com/script?"</a> &lt;&gt; bldr
--   "<a>http://example.com/script?Age=23&amp;Name=John+Doe"</a>
--   </pre>
buildUrlEncoded :: Map ByteString [ByteString] -> Builder

-- | Given a collection of key-value pairs with possibly duplicate keys
--   (represented as a <a>Map</a>), construct a string in
--   <tt>application/x-www-form-urlencoded</tt> format.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>printUrlEncoded</a> (<a>fromList</a> [(<a>Name</a>, ["John Doe"]), (<a>Age</a>, ["23"])])
--   "Age=23&amp;Name=John+Doe"
--   </pre>
printUrlEncoded :: Map ByteString [ByteString] -> ByteString
pCookies :: Parser [Cookie]
parseCookie :: ByteString -> Maybe [Cookie]
unsafeFromHex :: (Enum a, Num a, Bits a) => ByteString -> a
unsafeFromNat :: (Enum a, Num a, Bits a) => ByteString -> a

module Snap.Internal.Core

-- | <a>MonadSnap</a> is a type class, analogous to <a>MonadIO</a> for
--   <a>IO</a>, that makes it easy to wrap <a>Snap</a> inside monad
--   transformers.
class (Monad m, MonadIO m, MonadBaseControl IO m, MonadPlus m, Functor m, Applicative m, Alternative m) => MonadSnap m

-- | Lift a computation from the <a>Snap</a> monad.
liftSnap :: MonadSnap m => Snap a -> m a
data SnapResult a
SnapValue :: a -> SnapResult a
Zero :: Zero -> SnapResult a

-- | Type of external handler passed to <a>escapeHttp</a>.
type EscapeHttpHandler = ((Int -> Int) -> IO ()) " timeout modifier" -> InputStream ByteString " socket read end" -> OutputStream Builder " socket write end" -> IO ()

-- | Used internally to implement <a>escapeHttp</a>.
data EscapeSnap
TerminateConnection :: SomeException -> EscapeSnap
EscapeHttp :: EscapeHttpHandler -> EscapeSnap
data Zero
PassOnProcessing :: Zero
EarlyTermination :: Response -> Zero
EscapeSnap :: EscapeSnap -> Zero

-- | <a>Snap</a> is the <a>Monad</a> that user web handlers run in.
--   <a>Snap</a> gives you:
--   
--   <ol>
--   <li>Stateful access to fetch or modify an HTTP
--   <a>Request</a>.<pre>printRqContextPath :: Snap () printRqContextPath =
--   <a>writeBS</a> . <a>rqContextPath</a> =&lt;&lt; <a>getRequest</a>
--   </pre></li>
--   <li>Stateful access to fetch or modify an HTTP
--   <a>Response</a>.<pre>printRspStatusReason :: Snap ()
--   printRspStatusReason = <a>writeBS</a> . <a>rspStatusReason</a>
--   =&lt;&lt; <a>getResponse</a> </pre></li>
--   <li>Failure / <a>Alternative</a> / <a>MonadPlus</a> semantics: a
--   <a>Snap</a> handler can choose not to handle a given request, using
--   <a>empty</a> or its synonym <a>pass</a>, and you can try alternative
--   handlers with the <a>&lt;|&gt;</a> operator:<pre>a :: Snap String a =
--   <a>pass</a> b :: Snap String b = return "foo" c :: Snap String c = a
--   <a>&lt;|&gt;</a> b -- try running a, if it fails then try b
--   </pre></li>
--   <li>Convenience functions (<a>writeBS</a>, <a>writeLBS</a>,
--   <a>writeText</a>, <a>writeLazyText</a>, <a>addToOutput</a>) for
--   queueing output to be written to the <a>Response</a>, or for streaming
--   to the response using <a>io-streams</a>:<pre>example ::
--   (<a>OutputStream</a> <a>Builder</a> -&gt; IO (<a>OutputStream</a>
--   <a>Builder</a>)) -&gt; Snap () example streamProc = do <a>writeBS</a>
--   "I'm a strict bytestring" <a>writeLBS</a> "I'm a lazy bytestring"
--   <a>writeText</a> "I'm strict text" <a>addToOutput</a> streamProc
--   </pre></li>
--   <li>Early termination: if you call <a>finishWith</a>:<pre>a :: Snap ()
--   a = do <a>modifyResponse</a> $ <a>setResponseStatus</a> 500 "Internal
--   Server Error" <a>writeBS</a> "500 error" r &lt;- <a>getResponse</a>
--   <a>finishWith</a> r </pre>then any subsequent processing will be
--   skipped and the supplied <a>Response</a> value will be returned from
--   <a>runSnap</a> as-is.</li>
--   <li>Access to the <a>IO</a> monad through a <a>MonadIO</a>
--   instance:<pre>a :: Snap () a = <a>liftIO</a> fireTheMissiles
--   </pre></li>
--   <li>The ability to set or extend a timeout which will kill the handler
--   thread after <tt>N</tt> seconds of inactivity (the default is 20
--   seconds):<pre>a :: Snap () a = <a>setTimeout</a> 30 </pre></li>
--   <li>Throw and catch exceptions using a <a>MonadBaseControl</a>
--   instance:<pre>import <a>Control.Exception.Lifted</a>
--   (<a>SomeException</a>, <a>throwIO</a>, <a>catch</a>) foo :: Snap ()
--   foo = bar `catch` (e::<a>SomeException</a>) -&gt; baz where bar =
--   <a>throwIO</a> FooException </pre></li>
--   <li>Log a message to the error log:<pre>foo :: Snap () foo =
--   <a>logError</a> "grumble." </pre></li>
--   </ol>
--   
--   You may notice that most of the type signatures in this module contain
--   a <tt>(<a>MonadSnap</a> m) =&gt; ...</tt> typeclass constraint.
--   <a>MonadSnap</a> is a typeclass which, in essence, says "you can get
--   back to the <a>Snap</a> monad from here". Using <a>MonadSnap</a> you
--   can extend the <a>Snap</a> monad with additional functionality and
--   still have access to most of the <a>Snap</a> functions without writing
--   <a>lift</a> everywhere. Instances are already provided for most of the
--   common monad transformers (<a>ReaderT</a>, <a>WriterT</a>,
--   <a>StateT</a>, etc.).
newtype Snap a
Snap :: (forall r. (a -> SnapState -> IO r) -> (Zero -> SnapState -> IO r) -> SnapState -> IO r) -> Snap a
[unSnap] :: Snap a -> forall r. (a -> SnapState -> IO r) -> (Zero -> SnapState -> IO r) -> SnapState -> IO r
data SnapState
SnapState :: Request -> Response -> (ByteString -> IO ()) -> ((Int -> Int) -> IO ()) -> SnapState
[_snapRequest] :: SnapState -> Request
[_snapResponse] :: SnapState -> Response
[_snapLogError] :: SnapState -> ByteString -> IO ()
[_snapModifyTimeout] :: SnapState -> (Int -> Int) -> IO ()

-- | 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
--   <a>skipToEof</a>) before rethrowing the exception. If you used
--   <a>terminateConnection</a>, 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import qualified <a>Data.ByteString.Lazy</a> as L
--   ghci&gt; import <a>Data.Char</a> (toUpper)
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; :{
--   ghci| let f s = do u &lt;- Streams.map (B8.map toUpper) s
--   ghci|              l &lt;- Streams.toList u
--   ghci|              return $ L.fromChunks l
--   ghci| :}
--   ghci&gt; T.runHandler r (<a>runRequestBody</a> f &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:48:40 GMT
--   
--   SOME TEXT
--   </pre>
runRequestBody :: MonadSnap m => (InputStream ByteString -> IO a) -> m a

-- | Returns the request body as a lazy bytestring. /Note that the request
--   is not actually provided lazily!/
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; T.runHandler r (<a>readRequestBody</a> 2048 &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:08:44 GMT
--   
--   some text
--   </pre>
--   
--   <i>Since: 0.6</i>
readRequestBody :: MonadSnap m => Word64 -> m ByteString

-- | Normally Snap is careful to ensure that the request body is fully
--   consumed after your web handler runs, but before the <a>Response</a>
--   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 <a>finishWith</a>. Make sure you set any
--   content types, headers, cookies, etc. before you call this function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import <a>Data.Char</a> (toUpper)
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; let f = Streams.map (B8.map toUpper)
--   ghci&gt; T.runHandler r (<a>transformRequestBody</a> f &gt;&gt; <a>readRequestBody</a> 2048 &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:30:15 GMT
--   
--   SOME TEXT
--   </pre>
transformRequestBody :: (InputStream ByteString -> IO (InputStream ByteString)) -> Snap ()

-- | Short-circuits a <a>Snap</a> monad action early, storing the given
--   <a>Response</a> value in its state.
--   
--   IMPORTANT: Be vary careful when using this with things like a DB
--   library's <tt>withTransaction</tt> function or any other kind of
--   setup/teardown block, as it can prevent the cleanup from being called
--   and result in resource leaks.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Applicative</a>
--   ghci&gt; let r = T.get "/" M.empty
--   ghci&gt; T.runHandler r ((<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 16:58:57 GMT
--   
--   TOP
--   ghci&gt; let r' = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r' ((<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 17:50:50 GMT
--   </pre>
finishWith :: MonadSnap m => Response -> m a

-- | Capture the flow of control in case a handler calls <a>finishWith</a>.
--   
--   <i>WARNING</i>: in the event of a call to <a>transformRequestBody</a>
--   it is possible to violate HTTP protocol safety when using this
--   function. If you call <a>catchFinishWith</a> it is suggested that you
--   do not modify the body of the <a>Response</a> which was passed to the
--   <a>finishWith</a> call.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Applicative</a>
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let h = (<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>
--   ghci&gt; T.runHandler r (<a>catchFinishWith</a> h &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 18:35:42 GMT
--   
--   Left HTTP/1.1 200 OK
--   </pre>
catchFinishWith :: Snap a -> Snap (Either Response a)

-- | Fails out of a <a>Snap</a> monad action. This is used to indicate that
--   you choose not to handle the given request within the given handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r <a>pass</a>
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:35:42 GMT
--   
--   &lt;!DOCTYPE html&gt;
--   &lt;html&gt;
--   &lt;head&gt;
--   &lt;title&gt;Not found&lt;/title&gt;
--   &lt;/head&gt;
--   &lt;body&gt;
--   &lt;code&gt;No handler accepted "/foo/bar"<a>/code</a>
--   &lt;/body&gt;&lt;/html&gt;
--   </pre>
pass :: MonadSnap m => m a

-- | Runs a <a>Snap</a> monad action only if the request's HTTP method
--   matches the given method.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>method</a> <a>GET</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:38:48 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>method</a> <a>POST</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
method :: MonadSnap m => Method -> m a -> m a

-- | Runs a <a>Snap</a> monad action only if the request's HTTP method
--   matches one of the given methods.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>methods</a> [<a>GET</a>, <a>POST</a>] $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:38:48 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>methods</a> [<a>POST</a>] $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
methods :: MonadSnap m => [Method] -> m a -> m a
updateContextPath :: Int -> Request -> Request
pathWith :: MonadSnap m => (ByteString -> ByteString -> Bool) -> ByteString -> m a -> m a

-- | Runs a <a>Snap</a> monad action only when the <a>rqPathInfo</a> of the
--   request starts with the given path. For example,
--   
--   <pre>
--   dir "foo" handler
--   </pre>
--   
--   Will fail if <a>rqPathInfo</a> is not "<tt>/foo</tt>" or
--   "<tt>/foo/...</tt>", and will add <tt>"foo/"</tt> to the handler's
--   local <a>rqContextPath</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>dir</a> "foo" $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:52:24 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>dir</a> "baz" $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
dir :: MonadSnap m => ByteString -> m a -> m a

-- | Runs a <a>Snap</a> monad action only for requests where
--   <a>rqPathInfo</a> is exactly equal to the given string. If the path
--   matches, locally sets <a>rqContextPath</a> to the old value of
--   <a>rqPathInfo</a>, sets <a>rqPathInfo</a>="", and runs the given
--   handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; T.runHandler (T.get "/foo" M.empty) (<a>path</a> "foo" $ <a>writeBS</a> "bar")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:15:42 GMT
--   
--   bar
--   ghci&gt; T.runHandler (T.get "/foo" M.empty) (<a>path</a> "bar" $ <a>writeBS</a> "baz")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
path :: MonadSnap m => ByteString -> m a -> m a

-- | Runs a <a>Snap</a> 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
--   <tt>fromBS</tt>; this is new as of snap-core 0.10.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/11/foo/bar" M.empty
--   ghci&gt; let f = (\i -&gt; if i == 11 then <a>writeBS</a> "11" else <a>writeBS</a> "???")
--   ghci&gt; T.runHandler r (<a>pathArg</a> f)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:27:10 GMT
--   
--   11
--   ghci&gt; let r' = T.get "/foo/11/bar" M.empty
--   ghci&gt; T.runHandler r' (<a>pathArg</a> f)
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
pathArg :: (Readable a, MonadSnap m) => (a -> m b) -> m b

-- | Runs a <a>Snap</a> monad action only when <a>rqPathInfo</a> is empty.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/" M.empty
--   ghci&gt; T.runHandler r (<a>ifTop</a> $ <a>writeBS</a> <a>OK</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:56:39 GMT
--   
--   OK
--   ghci&gt; let r' = T.get "/foo" M.empty
--   ghci&gt; T.runHandler r' (<a>ifTop</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
ifTop :: MonadSnap m => m a -> m a

-- | Local Snap version of <tt>get</tt>.
sget :: Snap SnapState

-- | Local Snap monad version of <tt>modify</tt>.
smodify :: (SnapState -> SnapState) -> Snap ()

-- | Grabs the <a>Request</a> object out of the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> . <a>rqURI</a> =&lt;&lt; <a>getRequest</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 07:51:54 GMT
--   
--   /foo/bar
--   </pre>
getRequest :: MonadSnap m => m Request

-- | Grabs the <a>Response</a> object out of the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> . <a>rspStatusReason</a> =&lt;&lt; <a>getResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 15:06:00 GMT
--   
--   OK
--   </pre>
getResponse :: MonadSnap m => m Response

-- | Grabs something out of the <a>Request</a> object, using the given
--   projection function. See <tt>gets</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> =&lt;&lt; <a>getsRequest</a> <a>rqURI</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 07:51:54 GMT
--   
--   /foo/bar
--   </pre>
getsRequest :: MonadSnap m => (Request -> a) -> m a

-- | Grabs something out of the <a>Response</a> object, using the given
--   projection function. See <tt>gets</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> =&lt;&lt; <a>getsResponse</a> <a>rspStatusReason</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 13:35:45 GMT
--   
--   OK
--   </pre>
getsResponse :: MonadSnap m => (Response -> a) -> m a

-- | Puts a new <a>Request</a> object into the <a>Snap</a> monad. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; :{
--   ghci| let hndlr = do rq &lt;- T.buildRequest (T.get "/bar/foo" M.empty)
--   ghci|                <a>putRequest</a> rq
--   ghci|                uri' &lt;- <a>getsRequest</a> <a>rqURI</a>
--   ghci|                <a>writeBS</a> uri'
--   ghci| :}
--   ghci&gt; T.runHandler (T.get "/foo/bar" M.empty) hndlr
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:13:46 GMT
--   
--   /bar/foo
--   </pre>
putRequest :: MonadSnap m => Request -> m ()

-- | Puts a new <a>Response</a> object into the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let rsp = <a>setResponseCode</a> 404 <a>emptyResponse</a>
--   ghci&gt; let req = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler req (<a>putResponse</a> rsp)
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Wed, 06 Aug 2014 13:59:58 GMT
--   </pre>
putResponse :: MonadSnap m => Response -> m ()

-- | Modifies the <a>Request</a> object stored in a <a>Snap</a> monad.
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; r' &lt;- T.buildRequest $ T.get "/bar/foo" M.empty
--   ghci&gt; T.runHandler r (<a>modifyRequest</a> (const r') &gt;&gt; <a>getsRequest</a> <a>rqURI</a> &gt;&gt;= <a>writeBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:24:25 GMT
--   
--   /bar/foo
--   </pre>
modifyRequest :: MonadSnap m => (Request -> Request) -> m ()

-- | Modifes the <a>Response</a> object stored in a <a>Snap</a> monad.
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>modifyResponse</a> $ <a>setResponseCode</a> 404)
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:27:11 GMT
--   </pre>
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()

-- | Performs a redirect by setting the <tt>Location</tt> header to the
--   given target URL/path and the status code to 302 in the
--   <a>Response</a> object stored in a <a>Snap</a> monad. Note that the
--   target URL is not validated in any way. Consider using
--   <a>redirect'</a> instead, which allows you to choose the correct
--   status code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>redirect</a> "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
--   </pre>
redirect :: MonadSnap m => ByteString -> m a

-- | Performs a redirect by setting the <tt>Location</tt> header to the
--   given target URL/path and the status code (should be one of 301, 302,
--   303 or 307) in the <a>Response</a> object stored in a <a>Snap</a>
--   monad. Note that the target URL is not validated in any way.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>redirect'</a> "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
--   </pre>
redirect' :: MonadSnap m => ByteString -> Int -> m a

-- | Log an error message in the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; <a>runSnap</a> (<a>logError</a> "fatal error!") (<tt>error</tt> . B8.unpack) undefined undefined
--   *** Exception: fatal error!
--   </pre>
logError :: MonadSnap m => ByteString -> m ()

-- | Run the given stream procedure, adding its output to the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as B
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; :{
--   ghci| let f str = do {
--   ghci|   Streams.write (Just $ B.byteString "Hello, streams world") str;
--   ghci|   return str }
--   ghci| :}
--   ghci&gt; T.runHandler r (<a>addToOutput</a> f)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:55:47 GMT
--   
--   Hello, streams world
--   </pre>
addToOutput :: MonadSnap m => (OutputStream Builder -> IO (OutputStream Builder)) -> m ()

-- | Adds the given <a>Builder</a> to the body of the <a>Response</a>
--   stored in the | <a>Snap</a> monad state.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as B
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBuilder</a> $ B.byteString "Hello, world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:33:33 GMT
--   
--   Hello, world
--   </pre>
writeBuilder :: MonadSnap m => Builder -> m ()

-- | Adds the given strict <a>ByteString</a> to the body of the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> "Hello, bytestring world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:34:27 GMT
--   
--   Hello, bytestring world
--   </pre>
writeBS :: MonadSnap m => ByteString -> m ()

-- | Adds the given lazy <a>ByteString</a> to the body of the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeLBS</a> "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
--   </pre>
writeLBS :: MonadSnap m => ByteString -> m ()

-- | Adds the given strict <a>Text</a> to the body of the <a>Response</a>
--   stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeText</a> "Hello, text world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:36:38 GMT
--   
--   Hello, text world
--   </pre>
writeText :: MonadSnap m => Text -> m ()

-- | Adds the given lazy <a>Text</a> to the body of the <a>Response</a>
--   stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeLazyText</a> "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
--   </pre>
writeLazyText :: MonadSnap m => Text -> m ()

-- | Sets the output to be the contents of the specified file.
--   
--   Calling <a>sendFile</a> will overwrite any output queued to be sent in
--   the <a>Response</a>. If the response body is not modified after the
--   call to <a>sendFile</a>, Snap will use the efficient
--   <tt>sendfile()</tt> system call on platforms that support it.
--   
--   If the response body is modified (using <a>modifyResponseBody</a>),
--   the file will be read using <tt>mmap()</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; <tt>writeFile</tt> "/tmp/snap-file" "Hello, sendFile world"
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>sendFile</a> "/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
--   </pre>
sendFile :: MonadSnap m => FilePath -> m ()

-- | Sets the output to be the contents of the specified file, within the
--   given (start,end) range.
--   
--   Calling <a>sendFilePartial</a> will overwrite any output queued to be
--   sent in the <a>Response</a>. If the response body is not modified
--   after the call to <a>sendFilePartial</a>, Snap will use the efficient
--   <tt>sendfile()</tt> system call on platforms that support it.
--   
--   If the response body is modified (using <a>modifyResponseBody</a>),
--   the file will be read using <tt>mmap()</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; <tt>writeFile</tt> "/tmp/snap-file" "Hello, sendFilePartial world"
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>sendFilePartial</a> "/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
--   </pre>
sendFilePartial :: MonadSnap m => FilePath -> (Word64, Word64) -> m ()

-- | Runs a <a>Snap</a> action with a locally-modified <a>Request</a> state
--   object. The <a>Request</a> object in the Snap monad state after the
--   call to localRequest will be unchanged. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; r' &lt;- T.buildRequest $ T.get "/bar/foo" M.empty
--   ghci&gt; let printRqURI = <a>getsRequest</a> <a>rqURI</a> &gt;&gt;= <a>writeBS</a> &gt;&gt; <a>writeBS</a> "\n"
--   ghci&gt; T.runHandler r (printRqURI &gt;&gt; <a>localRequest</a> (const r') printRqURI)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:34:12 GMT
--   
--   /foo/bar
--   /bar/foo
--   </pre>
localRequest :: MonadSnap m => (Request -> Request) -> m a -> m a

-- | Fetches the <a>Request</a> from state and hands it to the given
--   action. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Monad.IO.Class</a>
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let h = <a>withRequest</a> (\rq -&gt; <a>liftIO</a> (T.requestToString rq) &gt;&gt;= <a>writeBS</a>)
--   ghci&gt; 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
--   </pre>
withRequest :: MonadSnap m => (Request -> m a) -> m a

-- | Fetches the <a>Response</a> from state and hands it to the given
--   action. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>withResponse</a> $ <a>writeBS</a> . <a>rspStatusReason</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:48:45 GMT
--   
--   OK
--   </pre>
withResponse :: MonadSnap m => (Response -> m a) -> m a

-- | Modifies the <a>Request</a> in the state to set the
--   <tt>rqRemoteAddr</tt> 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.
ipHeaderFilter :: MonadSnap m => m ()

-- | Modifies the <a>Request</a> in the state to set the
--   <tt>rqRemoteAddr</tt> 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.
ipHeaderFilter' :: MonadSnap m => CI ByteString -> m ()

-- | This function brackets a Snap action in resource acquisition and
--   release. This is provided because MonadCatchIO's <tt>bracket</tt>
--   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.
--   
--   <ol>
--   <li>Normal completion</li>
--   <li>Short-circuit completion, either from calling <tt>fail</tt> or
--   <a>finishWith</a></li>
--   <li>An exception being thrown.</li>
--   </ol>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let br = <a>bracketSnap</a> (putStrLn "before") (const $ putStrLn "after")
--   ghci&gt; 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
--   </pre>
bracketSnap :: IO a -> (a -> IO b) -> (a -> Snap c) -> Snap c

-- | This exception is thrown if the handler you supply to <a>runSnap</a>
--   fails.
data NoHandlerException
NoHandlerException :: String -> NoHandlerException

-- | Terminate the HTTP session with the given exception.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Control.Exception</a> as E
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (terminateConnection $ E.AssertionFailed "Assertion failed!")
--   *** Exception: &lt;terminated: Assertion failed!&gt;
--   </pre>
terminateConnection :: (Exception e, MonadSnap m) => e -> m a

-- | Terminate the HTTP session and hand control to some external handler,
--   escaping all further HTTP traffic.
--   
--   The external handler takes three arguments: a function to modify the
--   thread's timeout, and a read and a write ends to the socket.
escapeHttp :: MonadSnap m => EscapeHttpHandler -> m ()

-- | Runs a <a>Snap</a> monad action.
--   
--   This function is mostly intended for library writers; instead of
--   invoking <a>runSnap</a> directly, use <a>httpServe</a> or
--   <a>runHandler</a> (for testing).
runSnap :: Snap a -> (ByteString -> IO ()) -> ((Int -> Int) -> IO ()) -> Request -> IO (Request, Response)

-- | Post-process a finalized HTTP response:
--   
--   <ul>
--   <li>fixup content-length header</li>
--   <li>properly handle 204/304 responses</li>
--   <li>if request was HEAD, remove response body</li>
--   </ul>
--   
--   Note that we do NOT deal with transfer-encoding: chunked or
--   "connection: close" here.
fixupResponse :: Request -> Response -> IO Response
evalSnap :: Snap a -> (ByteString -> IO ()) -> ((Int -> Int) -> IO ()) -> Request -> IO a
getParamFrom :: MonadSnap m => (ByteString -> Request -> Maybe [ByteString]) -> ByteString -> m (Maybe ByteString)

-- | See <a>rqParam</a>. Looks up a value for the given named parameter in
--   the <a>Request</a>. If more than one value was entered for the given
--   parameter name, <a>getParam</a> gloms the values together with
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 12:57:20 GMT
--   
--   Just "bar"
--   </pre>
getParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqPostParam</a>. Looks up a value for the given named parameter
--   in the POST form parameters mapping in <a>Request</a>. If more than
--   one value was entered for the given parameter name,
--   <a>getPostParam</a> gloms the values together with:
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getPostParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:01:04 GMT
--   
--   Just "bar"
--   </pre>
getPostParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqQueryParam</a>. Looks up a value for the given named
--   parameter in the query string parameters mapping in <a>Request</a>. If
--   more than one value was entered for the given parameter name,
--   <a>getQueryParam</a> gloms the values together with
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" M.empty &gt;&gt; T.setQueryStringRaw "foo=bar&amp;foo=baz"
--   ghci&gt; T.runHandler r (<a>getQueryParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:06:50 GMT
--   
--   Just "bar baz"
--   </pre>
getQueryParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:02:54 GMT
--   
--   fromList [("foo",["bar"])]
--   </pre>
getParams :: MonadSnap m => m Params

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getPostParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:04:34 GMT
--   
--   fromList [("foo",["bar"])]
--   </pre>
getPostParams :: MonadSnap m => m Params

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" M.empty &gt;&gt; T.setQueryStringRaw "foo=bar&amp;foo=baz"
--   ghci&gt; T.runHandler r (<a>getQueryParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:10:17 GMT
--   
--   fromList [("foo",["bar","baz"])]
--   </pre>
getQueryParams :: MonadSnap m => m Params

-- | Gets the HTTP <a>Cookie</a> with the specified name.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>getCookie</a> "name" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 12:16:58 GMT
--   
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   </pre>
getCookie :: MonadSnap m => ByteString -> m (Maybe Cookie)

-- | Gets the HTTP <a>Cookie</a> with the specified name and decodes it. If
--   the decoding fails, the handler calls pass.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>readCookie</a> "name" &gt;&gt;= <a>writeBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 12:20:09 GMT
--   
--   value
--   </pre>
readCookie :: (MonadSnap m, Readable a) => ByteString -> m a

-- | Expire given <a>Cookie</a> in client's browser.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let cookie = Cookie "name" "" Nothing (Just "/subsite") Nothing True False
--   ghci&gt; T.runHandler r (<a>expireCookie</a> cookie)
--   HTTP/1.1 200 OK
--   set-cookie: name=; path=/subsite; expires=Sat, 24 Dec 1994 06:28:16 GMT; Secure
--   server: Snap/test
--   
--   date: Thu, 07 Aug 2014 12:21:27 GMT
--   ghci&gt; let cookie = Cookie "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r2 = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>getCookie</a> "name" &gt;&gt;= maybe (return ()) <a>expireCookie</a>)
--   HTTP/1.1 200 OK
--   set-cookie: name=; expires=Sat, 24 Dec 1994 06:28:16 GMT
--   server: Snap/test
--   </pre>
expireCookie :: MonadSnap m => Cookie -> m ()

-- | Causes the handler thread to be killed <tt>n</tt> seconds from now.
setTimeout :: MonadSnap m => Int -> m ()

-- | Causes the handler thread to be killed at least <tt>n</tt> seconds
--   from now.
extendTimeout :: MonadSnap m => Int -> m ()

-- | Modifies the amount of time remaining before the request times out.
modifyTimeout :: MonadSnap m => (Int -> Int) -> m ()

-- | Returns an <a>IO</a> action which you can use to modify the timeout
--   value.
getTimeoutModifier :: MonadSnap m => m ((Int -> Int) -> IO ())

-- | Represents an HTTP response.
data Response
Response :: Headers -> Map ByteString Cookie -> !Maybe Word64 -> ResponseBody -> !Int -> !ByteString -> !Bool -> Response
[rspHeaders] :: Response -> Headers
[rspCookies] :: Response -> Map ByteString Cookie

-- | 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.
[rspContentLength] :: Response -> !Maybe Word64
[rspBody] :: Response -> ResponseBody

-- | Returns the HTTP status code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatus <a>emptyResponse</a>
--   200
--   </pre>
[rspStatus] :: Response -> !Int

-- | Returns the HTTP status explanation string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatusReason <a>emptyResponse</a>
--   <a>OK</a>
--   </pre>
[rspStatusReason] :: Response -> !ByteString

-- | If true, we are transforming the request body with
--   <tt>transformRequestBody</tt>
[rspTransformingRqBody] :: Response -> !Bool
data ResponseBody

-- | output body is a function that writes to a <a>Builder</a> stream
Stream :: StreamProc -> ResponseBody

-- | output body is sendfile(), optional second argument is a byte range to
--   send
SendFile :: FilePath -> Maybe (Word64, Word64) -> ResponseBody
type StreamProc = OutputStream Builder -> IO (OutputStream Builder)

-- | Contains all of the information about an incoming HTTP request.
data Request
Request :: ByteString -> ByteString -> {-# UNPACK #-} !Int -> ByteString -> {-# UNPACK #-} !Int -> ByteString -> !Bool -> Headers -> InputStream ByteString -> !Maybe Word64 -> !Method -> {-# UNPACK #-} !HttpVersion -> [Cookie] -> ByteString -> ByteString -> ByteString -> ByteString -> Params -> Params -> Params -> Request

-- | The server name of the request, as it came in from the request's
--   <tt>Host:</tt> header.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.get "/foo/bar" M.empty
--   ghci|         T.setHeader "host" "example.com"
--   ghci| :}
--   ghci&gt; rqHostName rq
--   "example.com"
--   </pre>
[rqHostName] :: Request -> ByteString

-- | The remote IP address.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
[rqClientAddr] :: Request -> ByteString

-- | The remote TCP port number.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "60000"
--   </pre>
[rqClientPort] :: Request -> {-# UNPACK #-} !Int

-- | The local IP address for this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
[rqServerAddr] :: Request -> ByteString

-- | 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   8080
--   </pre>
[rqServerPort] :: Request -> {-# UNPACK #-} !Int

-- | Returns the HTTP server's idea of its local hostname, including port.
--   This is as configured with the <tt>Config</tt> object at startup.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqLocalHostname `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "localhost"
--   </pre>
[rqLocalHostname] :: Request -> ByteString

-- | Returns <tt>True</tt> if this is an HTTPS session.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqIsSecure `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   False
--   </pre>
[rqIsSecure] :: Request -> !Bool

-- | Contains all HTTP <a>Headers</a> associated with this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqHeaders `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   H {unH = [("host","localhost")]}
--   </pre>
[rqHeaders] :: Request -> Headers

-- | Actual body of the request.
[rqBody] :: Request -> InputStream ByteString

-- | Returns the <tt>Content-Length</tt> of the HTTP request body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContentLength `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   Nothing
--   </pre>
[rqContentLength] :: Request -> !Maybe Word64

-- | Returns the HTTP request method.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqMethod `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   GET
--   </pre>
[rqMethod] :: Request -> !Method

-- | Returns the HTTP version used by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqVersion `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   (1,1)
--   </pre>
[rqVersion] :: Request -> {-# UNPACK #-} !HttpVersion

-- | Returns a list of the cookies that came in from the HTTP request
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqCookies `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   []
--   </pre>
[rqCookies] :: Request -> [Cookie]

-- | Handlers can be hung on a <tt>URI</tt> "entry point"; this is called
--   the "context path". If a handler is hung on the context path
--   <tt>"/foo/"</tt>, and you request <tt>"/foo/bar"</tt>, the value of
--   <a>rqPathInfo</a> will be <tt>"bar"</tt>.
--   
--   The following identity holds:
--   
--   <pre>
--   rqURI r == S.concat [ rqContextPath r
--                       , rqPathInfo r
--                       , let q = rqQueryString r
--                         in if S.null q
--                              then ""
--                              else S.append "?" q
--                       ]
--   </pre>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqPathInfo `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
[rqPathInfo] :: Request -> ByteString

-- | The "context path" of the request; catenating <a>rqContextPath</a>,
--   and <a>rqPathInfo</a> should get you back to the original <a>rqURI</a>
--   (ignoring query strings). The <a>rqContextPath</a> always begins and
--   ends with a slash (<tt>"/"</tt>) character, and represents the path
--   (relative to your component/snaplet) you took to get to your handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContextPath `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "/"
--   </pre>
[rqContextPath] :: Request -> ByteString

-- | Returns the <tt>URI</tt> requested by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqURI `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
[rqURI] :: Request -> ByteString

-- | Returns the HTTP query string for this <a>Request</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rq &lt;- T.buildRequest (T.get "/foo/bar" (M.fromList [("name", ["value"])]))
--   ghci&gt; rqQueryString rq
--   "name=value"
--   </pre>
[rqQueryString] :: Request -> ByteString

-- | Returns the parameters mapping for this <a>Request</a>. "Parameters"
--   are automatically decoded from the URI's query string and
--   <tt>POST</tt> body and entered into this mapping. The <a>rqParams</a>
--   value is thus a union of <a>rqQueryParams</a> and <a>rqPostParams</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqParams rq
--   fromList [("baz",["qux","quux"])]
--   </pre>
[rqParams] :: Request -> Params

-- | The parameter mapping decoded from the URI's query string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqQueryParams rq
--   fromList [("baz",["quux"])]
--   </pre>
[rqQueryParams] :: Request -> Params

-- | The parameter mapping decoded from the POST body. Note that Snap only
--   auto-decodes POST request bodies when the request's
--   <tt>Content-Type</tt> is <tt>application/x-www-form-urlencoded</tt>.
--   For <tt>multipart/form-data</tt> use <a>handleFileUploads</a> to
--   decode the POST request and fill this mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqPostParams rq
--   fromList [("baz",["qux"])]
--   </pre>
[rqPostParams] :: Request -> Params

-- | A type alias for the HTTP parameters mapping. Each parameter key maps
--   to a list of <a>ByteString</a> values; if a parameter is specified
--   multiple times (e.g.: "<tt>GET /foo?param=bar1&amp;param=bar2</tt>"),
--   looking up "<tt>param</tt>" in the mapping will give you <tt>["bar1",
--   "bar2"]</tt>.
type Params = Map ByteString [ByteString]

-- | A datatype representing an HTTP cookie.
data Cookie
Cookie :: !ByteString -> !ByteString -> !Maybe UTCTime -> !Maybe ByteString -> !Maybe ByteString -> !Bool -> !Bool -> Cookie

-- | The name of the cookie.
[cookieName] :: Cookie -> !ByteString

-- | The cookie's string value.
[cookieValue] :: Cookie -> !ByteString

-- | The cookie's expiration value, if it has one.
[cookieExpires] :: Cookie -> !Maybe UTCTime

-- | The cookie's "domain" value, if it has one.
[cookieDomain] :: Cookie -> !Maybe ByteString

-- | The cookie path.
[cookiePath] :: Cookie -> !Maybe ByteString

-- | Tag as secure cookie?
[cookieSecure] :: Cookie -> !Bool

-- | HTTP only?
[cookieHttpOnly] :: Cookie -> !Bool

-- | Represents a (major, minor) version of the HTTP protocol.
type HttpVersion = (Int, Int)

-- | Enumerates the HTTP method values (see
--   <a>http://tools.ietf.org/html/rfc2068.html#section-5.1.1</a>).
data Method
GET :: Method
HEAD :: Method
POST :: Method
PUT :: Method
DELETE :: Method
TRACE :: Method
OPTIONS :: Method
CONNECT :: Method
PATCH :: Method
Method :: ByteString -> Method

-- | A typeclass for datatypes which contain HTTP headers.
class HasHeaders a

-- | Modify the datatype's headers.
updateHeaders :: HasHeaders a => (Headers -> Headers) -> a -> a

-- | Retrieve the headers from a datatype that has headers.
headers :: HasHeaders a => a -> Headers

-- | Adds a header key-value-pair to the <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, the new value is appended to
--   the headers list.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>addHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; <a>addHeader</a> "Host" "127.0.0.1" it
--   H {unH = [("host","localhost,127.0.0.1")]}
--   </pre>
addHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Sets a header key-value-pair in a <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, it is overwritten with the
--   new value.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; setHeader "Host" "127.0.0.1" it
--   H {unH = [("host","127.0.0.1")]}
--   </pre>
setHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Gets a header value out of a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>getHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   Just "localhost"
--   </pre>
getHeader :: HasHeaders a => CI ByteString -> a -> Maybe ByteString

-- | Lists all the headers out of a <a>HasHeaders</a> datatype. If many
--   headers came in with the same name, they will be catenated together.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>listHeaders</a> $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   [("host","localhost")]
--   </pre>
listHeaders :: HasHeaders a => a -> [(CI ByteString, ByteString)]

-- | Clears a header value from a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>deleteHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = []}
--   </pre>
deleteHeader :: HasHeaders a => CI ByteString -> a -> a

-- | Equate the special case constructors with their corresponding
--   <tt>Method name</tt> variant.
normalizeMethod :: Method -> Method
rspBodyMap :: (StreamProc -> StreamProc) -> ResponseBody -> ResponseBody
rspBodyToEnum :: ResponseBody -> StreamProc

-- | 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 <tt>Content-Type</tt> is
--   <tt>application/x-www-form-urlencoded</tt>). Parameter values can be
--   modified within handlers using "rqModifyParams".
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParam</a> "baz" rq
--   Just ["qux","quux"]
--   </pre>
rqParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the POST
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqPostParam</a> "baz" rq
--   Just ["qux"]
--   </pre>
rqPostParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the query
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqQueryParam</a> "baz" rq
--   Just ["quux"]
--   </pre>
rqQueryParam :: ByteString -> Request -> Maybe [ByteString]

-- | Modifies the parameters mapping (which is a <tt>Map ByteString
--   ByteString</tt>) in a <a>Request</a> using the given function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqModifyParams</a> (M.delete "baz") rq
--   fromList []
--   </pre>
rqModifyParams :: (Params -> Params) -> Request -> Request

-- | Writes a key-value pair to the parameters mapping within the given
--   request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqSetParam</a> "baz" ["corge"] rq
--   fromList [("baz", ["corge"])]
--   </pre>
rqSetParam :: ByteString -> [ByteString] -> Request -> Request

-- | An empty <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
emptyResponse :: Response

-- | Sets an HTTP response body to the given stream procedure.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   </pre>
setResponseBody :: (OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Sets the HTTP response status. Note: normally you would use
--   <a>setResponseCode</a> unless you needed a custom response
--   explanation.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setResponseStatus 500 "Internal Server Error" <a>emptyResponse</a>
--   HTTP/1.1 500 Internal Server Error
--   </pre>
setResponseStatus :: Int -> ByteString -> Response -> Response

-- | Sets the HTTP response code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setResponseCode 404 <a>emptyResponse</a>
--   HTTP/1.1 404 Not Found
--   </pre>
setResponseCode :: Int -> Response -> Response

-- | Modifies a response body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   ghci&gt; :{
--   ghci| let r' = <a>modifyResponseBody</a>
--   ghci|          (f out -&gt; do
--   ghci|              out' &lt;- f out
--   ghci|              Streams.write (Just $ Builder.<a>byteString</a> "\nBye, world!") out'
--   ghci|              return out') r
--   ghci| :}
--   ghci&gt; r'
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   Bye, world!
--   </pre>
modifyResponseBody :: ((OutputStream Builder -> IO (OutputStream Builder)) -> OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Sets the <tt>Content-Type</tt> in the <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setContentType "text/html" <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   content-type: text/html
--   </pre>
setContentType :: ByteString -> Response -> Response

-- | Adds an HTTP <a>Cookie</a> to <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   </pre>
addResponseCookie :: Cookie -> Response -> Response

-- | Gets an HTTP <a>Cookie</a> with the given name from <a>Response</a>
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>getResponseCookie</a> "cookie-name" <a>emptyResponse</a>
--   Nothing
--   </pre>
getResponseCookie :: ByteString -> Response -> Maybe Cookie

-- | Returns a list of <a>Cookie</a>s present in <a>Response</a>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>getResponseCookies</a> <a>emptyResponse</a>
--   []
--   </pre>
getResponseCookies :: Response -> [Cookie]

-- | Deletes an HTTP <a>Cookie</a> from the <a>Response</a> headers. Please
--   note this does not necessarily erase the cookie from the client
--   browser.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>deleteResponseCookie</a> "name" rsp
--   Nothing
--   </pre>
deleteResponseCookie :: ByteString -> Response -> Response

-- | Modifies an HTTP <a>Cookie</a> with given name in <a>Response</a>
--   headers. Nothing will happen if a matching <a>Cookie</a> can not be
--   found in <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; let f ck@(<a>Cookie</a> { cookieName = name }) = ck { cookieName = name &lt;&gt; "'"}
--   ghci&gt; let rsp' = <a>modifyResponseCookie</a> "name" f rsp
--   ghci&gt; <a>getResponseCookie</a> "name'" rsp'
--   Just (Cookie {cookieName = "name'", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" rsp'
--   Just (Cookie {cookieName = "name", ...})
--   </pre>
modifyResponseCookie :: ByteString -> (Cookie -> Cookie) -> Response -> Response

-- | A note here: if you want to set the <tt>Content-Length</tt> for the
--   response, Snap forces you to do it with this function rather than by
--   setting it in the headers; the <tt>Content-Length</tt> in the headers
--   will be ignored.
--   
--   The reason for this is that Snap needs to look up the value of
--   <tt>Content-Length</tt> 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 <tt>Connection:
--   close</tt>. For HTTP/1.1 clients, Snap will switch to the chunked
--   transfer encoding if <tt>Content-Length</tt> is not specified.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setContentLength 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   Content-Length: 400
--   </pre>
setContentLength :: Word64 -> Response -> Response

-- | Removes any <tt>Content-Length</tt> set in the <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; clearContentLength $ <a>setContentLength</a> 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
clearContentLength :: Response -> Response

-- | Convert a <a>CTime</a> into an HTTP timestamp.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>formatHttpTime</a> . <a>fromIntegral</a> $ 10
--   "Thu, 01 Jan 1970 00:00:10 GMT"
--   </pre>
formatHttpTime :: CTime -> IO ByteString

-- | Convert a <a>CTime</a> into common log entry format.
formatLogTime :: CTime -> IO ByteString

-- | Converts an HTTP timestamp into a <a>CTime</a>.
--   
--   If the given time string is unparseable, this function will return 0.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>parseHttpTime</a> "Thu, 01 Jan 1970 00:00:10 GMT"
--   10
--   </pre>
parseHttpTime :: ByteString -> IO CTime

-- | Adapted from:
--   
--   
--   <a>https://www.iana.org/assignments/http-status-codes/http-status-codes.txt</a>
statusReasonMap :: IntMap ByteString
instance GHC.Classes.Eq Snap.Internal.Core.NoHandlerException
instance GHC.Show.Show Snap.Internal.Core.NoHandlerException
instance GHC.Exception.Type.Exception Snap.Internal.Core.NoHandlerException
instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO Snap.Internal.Core.Snap
instance Snap.Internal.Core.MonadSnap Snap.Internal.Core.Snap
instance GHC.Base.Monad Snap.Internal.Core.Snap
instance Control.Monad.Fail.MonadFail Snap.Internal.Core.Snap
instance Control.Monad.IO.Class.MonadIO Snap.Internal.Core.Snap
instance Control.Monad.Base.MonadBase GHC.Types.IO Snap.Internal.Core.Snap
instance GHC.Base.MonadPlus Snap.Internal.Core.Snap
instance GHC.Base.Functor Snap.Internal.Core.Snap
instance GHC.Base.Applicative Snap.Internal.Core.Snap
instance GHC.Base.Alternative Snap.Internal.Core.Snap
instance GHC.Exception.Type.Exception Snap.Internal.Core.EscapeSnap
instance GHC.Show.Show Snap.Internal.Core.EscapeSnap


-- | This module contains the core type definitions, class instances, and
--   functions for HTTP as well as the <a>Snap</a> monad, which is used for
--   web handlers.
module Snap.Core

-- | <a>Snap</a> is the <a>Monad</a> that user web handlers run in.
--   <a>Snap</a> gives you:
--   
--   <ol>
--   <li>Stateful access to fetch or modify an HTTP
--   <a>Request</a>.<pre>printRqContextPath :: Snap () printRqContextPath =
--   <a>writeBS</a> . <a>rqContextPath</a> =&lt;&lt; <a>getRequest</a>
--   </pre></li>
--   <li>Stateful access to fetch or modify an HTTP
--   <a>Response</a>.<pre>printRspStatusReason :: Snap ()
--   printRspStatusReason = <a>writeBS</a> . <a>rspStatusReason</a>
--   =&lt;&lt; <a>getResponse</a> </pre></li>
--   <li>Failure / <a>Alternative</a> / <a>MonadPlus</a> semantics: a
--   <a>Snap</a> handler can choose not to handle a given request, using
--   <a>empty</a> or its synonym <a>pass</a>, and you can try alternative
--   handlers with the <a>&lt;|&gt;</a> operator:<pre>a :: Snap String a =
--   <a>pass</a> b :: Snap String b = return "foo" c :: Snap String c = a
--   <a>&lt;|&gt;</a> b -- try running a, if it fails then try b
--   </pre></li>
--   <li>Convenience functions (<a>writeBS</a>, <a>writeLBS</a>,
--   <a>writeText</a>, <a>writeLazyText</a>, <a>addToOutput</a>) for
--   queueing output to be written to the <a>Response</a>, or for streaming
--   to the response using <a>io-streams</a>:<pre>example ::
--   (<a>OutputStream</a> <a>Builder</a> -&gt; IO (<a>OutputStream</a>
--   <a>Builder</a>)) -&gt; Snap () example streamProc = do <a>writeBS</a>
--   "I'm a strict bytestring" <a>writeLBS</a> "I'm a lazy bytestring"
--   <a>writeText</a> "I'm strict text" <a>addToOutput</a> streamProc
--   </pre></li>
--   <li>Early termination: if you call <a>finishWith</a>:<pre>a :: Snap ()
--   a = do <a>modifyResponse</a> $ <a>setResponseStatus</a> 500 "Internal
--   Server Error" <a>writeBS</a> "500 error" r &lt;- <a>getResponse</a>
--   <a>finishWith</a> r </pre>then any subsequent processing will be
--   skipped and the supplied <a>Response</a> value will be returned from
--   <a>runSnap</a> as-is.</li>
--   <li>Access to the <a>IO</a> monad through a <a>MonadIO</a>
--   instance:<pre>a :: Snap () a = <a>liftIO</a> fireTheMissiles
--   </pre></li>
--   <li>The ability to set or extend a timeout which will kill the handler
--   thread after <tt>N</tt> seconds of inactivity (the default is 20
--   seconds):<pre>a :: Snap () a = <a>setTimeout</a> 30 </pre></li>
--   <li>Throw and catch exceptions using a <a>MonadBaseControl</a>
--   instance:<pre>import <a>Control.Exception.Lifted</a>
--   (<a>SomeException</a>, <a>throwIO</a>, <a>catch</a>) foo :: Snap ()
--   foo = bar `catch` (e::<a>SomeException</a>) -&gt; baz where bar =
--   <a>throwIO</a> FooException </pre></li>
--   <li>Log a message to the error log:<pre>foo :: Snap () foo =
--   <a>logError</a> "grumble." </pre></li>
--   </ol>
--   
--   You may notice that most of the type signatures in this module contain
--   a <tt>(<a>MonadSnap</a> m) =&gt; ...</tt> typeclass constraint.
--   <a>MonadSnap</a> is a typeclass which, in essence, says "you can get
--   back to the <a>Snap</a> monad from here". Using <a>MonadSnap</a> you
--   can extend the <a>Snap</a> monad with additional functionality and
--   still have access to most of the <a>Snap</a> functions without writing
--   <a>lift</a> everywhere. Instances are already provided for most of the
--   common monad transformers (<a>ReaderT</a>, <a>WriterT</a>,
--   <a>StateT</a>, etc.).
data Snap a

-- | Runs a <a>Snap</a> monad action.
--   
--   This function is mostly intended for library writers; instead of
--   invoking <a>runSnap</a> directly, use <a>httpServe</a> or
--   <a>runHandler</a> (for testing).
runSnap :: Snap a -> (ByteString -> IO ()) -> ((Int -> Int) -> IO ()) -> Request -> IO (Request, Response)

-- | <a>MonadSnap</a> is a type class, analogous to <a>MonadIO</a> for
--   <a>IO</a>, that makes it easy to wrap <a>Snap</a> inside monad
--   transformers.
class (Monad m, MonadIO m, MonadBaseControl IO m, MonadPlus m, Functor m, Applicative m, Alternative m) => MonadSnap m

-- | Lift a computation from the <a>Snap</a> monad.
liftSnap :: MonadSnap m => Snap a -> m a

-- | This exception is thrown if the handler you supply to <a>runSnap</a>
--   fails.
data NoHandlerException
NoHandlerException :: String -> NoHandlerException

-- | This function brackets a Snap action in resource acquisition and
--   release. This is provided because MonadCatchIO's <tt>bracket</tt>
--   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.
--   
--   <ol>
--   <li>Normal completion</li>
--   <li>Short-circuit completion, either from calling <tt>fail</tt> or
--   <a>finishWith</a></li>
--   <li>An exception being thrown.</li>
--   </ol>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let br = <a>bracketSnap</a> (putStrLn "before") (const $ putStrLn "after")
--   ghci&gt; 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
--   </pre>
bracketSnap :: IO a -> (a -> IO b) -> (a -> Snap c) -> Snap c

-- | Short-circuits a <a>Snap</a> monad action early, storing the given
--   <a>Response</a> value in its state.
--   
--   IMPORTANT: Be vary careful when using this with things like a DB
--   library's <tt>withTransaction</tt> function or any other kind of
--   setup/teardown block, as it can prevent the cleanup from being called
--   and result in resource leaks.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Applicative</a>
--   ghci&gt; let r = T.get "/" M.empty
--   ghci&gt; T.runHandler r ((<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 16:58:57 GMT
--   
--   TOP
--   ghci&gt; let r' = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r' ((<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 17:50:50 GMT
--   </pre>
finishWith :: MonadSnap m => Response -> m a

-- | Capture the flow of control in case a handler calls <a>finishWith</a>.
--   
--   <i>WARNING</i>: in the event of a call to <a>transformRequestBody</a>
--   it is possible to violate HTTP protocol safety when using this
--   function. If you call <a>catchFinishWith</a> it is suggested that you
--   do not modify the body of the <a>Response</a> which was passed to the
--   <a>finishWith</a> call.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Applicative</a>
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let h = (<a>ifTop</a> $ <a>writeBS</a> "TOP") &lt;|&gt; <a>finishWith</a> <a>emptyResponse</a>
--   ghci&gt; T.runHandler r (<a>catchFinishWith</a> h &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 18:35:42 GMT
--   
--   Left HTTP/1.1 200 OK
--   </pre>
catchFinishWith :: Snap a -> Snap (Either Response a)

-- | Fails out of a <a>Snap</a> monad action. This is used to indicate that
--   you choose not to handle the given request within the given handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r <a>pass</a>
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:35:42 GMT
--   
--   &lt;!DOCTYPE html&gt;
--   &lt;html&gt;
--   &lt;head&gt;
--   &lt;title&gt;Not found&lt;/title&gt;
--   &lt;/head&gt;
--   &lt;body&gt;
--   &lt;code&gt;No handler accepted "/foo/bar"<a>/code</a>
--   &lt;/body&gt;&lt;/html&gt;
--   </pre>
pass :: MonadSnap m => m a

-- | Type of external handler passed to <a>escapeHttp</a>.
type EscapeHttpHandler = ((Int -> Int) -> IO ()) " timeout modifier" -> InputStream ByteString " socket read end" -> OutputStream Builder " socket write end" -> IO ()

-- | Used internally to implement <a>escapeHttp</a>.
data EscapeSnap
TerminateConnection :: SomeException -> EscapeSnap
EscapeHttp :: EscapeHttpHandler -> EscapeSnap

-- | Terminate the HTTP session and hand control to some external handler,
--   escaping all further HTTP traffic.
--   
--   The external handler takes three arguments: a function to modify the
--   thread's timeout, and a read and a write ends to the socket.
escapeHttp :: MonadSnap m => EscapeHttpHandler -> m ()

-- | Terminate the HTTP session with the given exception.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Control.Exception</a> as E
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (terminateConnection $ E.AssertionFailed "Assertion failed!")
--   *** Exception: &lt;terminated: Assertion failed!&gt;
--   </pre>
terminateConnection :: (Exception e, MonadSnap m) => e -> m a

-- | Runs a <a>Snap</a> monad action only if the request's HTTP method
--   matches the given method.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>method</a> <a>GET</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:38:48 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>method</a> <a>POST</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
method :: MonadSnap m => Method -> m a -> m a

-- | Runs a <a>Snap</a> monad action only if the request's HTTP method
--   matches one of the given methods.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>methods</a> [<a>GET</a>, <a>POST</a>] $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 13:38:48 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>methods</a> [<a>POST</a>] $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
methods :: MonadSnap m => [Method] -> m a -> m a

-- | Runs a <a>Snap</a> monad action only for requests where
--   <a>rqPathInfo</a> is exactly equal to the given string. If the path
--   matches, locally sets <a>rqContextPath</a> to the old value of
--   <a>rqPathInfo</a>, sets <a>rqPathInfo</a>="", and runs the given
--   handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; T.runHandler (T.get "/foo" M.empty) (<a>path</a> "foo" $ <a>writeBS</a> "bar")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:15:42 GMT
--   
--   bar
--   ghci&gt; T.runHandler (T.get "/foo" M.empty) (<a>path</a> "bar" $ <a>writeBS</a> "baz")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
path :: MonadSnap m => ByteString -> m a -> m a

-- | Runs a <a>Snap</a> 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
--   <tt>fromBS</tt>; this is new as of snap-core 0.10.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/11/foo/bar" M.empty
--   ghci&gt; let f = (\i -&gt; if i == 11 then <a>writeBS</a> "11" else <a>writeBS</a> "???")
--   ghci&gt; T.runHandler r (<a>pathArg</a> f)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:27:10 GMT
--   
--   11
--   ghci&gt; let r' = T.get "/foo/11/bar" M.empty
--   ghci&gt; T.runHandler r' (<a>pathArg</a> f)
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
pathArg :: (Readable a, MonadSnap m) => (a -> m b) -> m b

-- | Runs a <a>Snap</a> monad action only when the <a>rqPathInfo</a> of the
--   request starts with the given path. For example,
--   
--   <pre>
--   dir "foo" handler
--   </pre>
--   
--   Will fail if <a>rqPathInfo</a> is not "<tt>/foo</tt>" or
--   "<tt>/foo/...</tt>", and will add <tt>"foo/"</tt> to the handler's
--   local <a>rqContextPath</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>dir</a> "foo" $ <a>writeBS</a> "OK")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:52:24 GMT
--   
--   OK
--   ghci&gt; T.runHandler r (<a>dir</a> "baz" $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
dir :: MonadSnap m => ByteString -> m a -> m a

-- | Runs a <a>Snap</a> monad action only when <a>rqPathInfo</a> is empty.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/" M.empty
--   ghci&gt; T.runHandler r (<a>ifTop</a> $ <a>writeBS</a> <a>OK</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 14:56:39 GMT
--   
--   OK
--   ghci&gt; let r' = T.get "/foo" M.empty
--   ghci&gt; T.runHandler r' (<a>ifTop</a> $ <a>writeBS</a> "OK")
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
ifTop :: MonadSnap m => m a -> m a

-- | A web handler which, given a mapping from URL entry points to web
--   handlers, efficiently routes requests to the correct handler.
--   
--   <b>Usage</b>
--   
--   The URL entry points are given as relative paths, for example:
--   
--   <pre>
--   route [ ("foo/bar/quux", fooBarQuux) ]
--   </pre>
--   
--   If the URI of the incoming request is <tt>/foo/bar/quux</tt> or
--   <tt>/foo/bar/quux/...anything...</tt> then the request will be routed
--   to <tt>"fooBarQuux"</tt>, with <a>rqContextPath</a> set to
--   <tt>"/foo/bar/quux/"</tt> and <a>rqPathInfo</a> set to
--   <tt>"...anything..."</tt>.
--   
--   A path component within an URL entry point beginning with a colon
--   (<tt>":"</tt>) is treated as a <i>variable capture</i>; the
--   corresponding path component within the request URI will be entered
--   into the <a>rqParams</a> parameters mapping with the given name. For
--   instance, if the routes were:
--   
--   <pre>
--   route [ ("foo/:bar/baz", fooBazHandler) ]
--   </pre>
--   
--   Then a request for <tt>"/foo/saskatchewan/baz"</tt> would be routed to
--   <tt>fooBazHandler</tt> with a mapping for <tt>"bar" =&gt;
--   "saskatchewan"</tt> in its parameters table.
--   
--   Longer paths are matched first, and specific routes are matched before
--   captures. That is, if given routes:
--   
--   <pre>
--   [ ("a", h1), ("a/b", h2), ("a/:x", h3) ]
--   </pre>
--   
--   a request for <tt>"/a/b"</tt> will go to <tt>h2</tt>, <tt>"/a/s"</tt>
--   for any <i>s</i> will go to <tt>h3</tt>, and <tt>"/a"</tt> will go to
--   <tt>h1</tt>.
--   
--   The following example matches <tt>"/article"</tt> to an article index,
--   <tt>"/login"</tt> to a login, and <tt>"/article/..."</tt> to an
--   article renderer.
--   
--   <pre>
--   <a>route</a> [ ("article",     renderIndex)
--         , ("article/:id", renderArticle)
--         , ("login",       <a>method</a> POST doLogin) ]
--   </pre>
--   
--   <b>Note: URL decoding</b>
--   
--   A short note about URL decoding: path matching and variable capture
--   are done on <i>decoded</i> URLs, but the contents of
--   <a>rqContextPath</a> and <a>rqPathInfo</a> will contain the original
--   encoded URL, i.e. what the user entered. For example, in the following
--   scenario:
--   
--   <pre>
--   route [ ("a b c d/", foo ) ]
--   </pre>
--   
--   A request for "<tt>/a+b+c+d</tt>" will be sent to <tt>foo</tt> with
--   <a>rqContextPath</a> set to <tt>"<i>a+b+c+d</i>"</tt>.
--   
--   This behaviour changed as of Snap 0.6.1; previous versions had
--   unspecified (and buggy!) semantics here.
--   
--   <b>Example:</b>
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as Map
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import <a>Snap.Test</a>
--   ghci&gt; :{
--   ghci| let handler = do r &lt;- <a>getRequest</a>
--   ghci|                  <a>writeBS</a> $ "rqContextPath: " &lt;&gt; <a>rqContextPath</a> r &lt;&gt; "\n"
--   ghci|                  <a>writeBS</a> $ "rqPathInfo: " &lt;&gt; <a>rqPathInfo</a> r &lt;&gt; "\n"
--   ghci|                  <a>writeBS</a> $ "rqParams: " &lt;&gt; (B8.pack . show $ <a>rqParams</a> r)
--   ghci| :}
--   ghci&gt; <a>runHandler</a> (<a>get</a> "/foo/bar" "Map.empty") (<a>route</a> [("foo", handler)])
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 05:16:59 GMT
--   
--   rqContextPath: /foo/
--   rqPathInfo: bar
--   rqParams: fromList []
--   ghci&gt; <a>runHandler</a> (<a>get</a> "/foo/bar" "Map.empty") (<a>route</a> [("foo/:bar", handler)])
--   [...]
--   
--   rqContextPath: /foo/bar/
--   rqPathInfo:
--   rqParams: fromList [("bar",["bar"])]
--   </pre>
route :: MonadSnap m => [(ByteString, m a)] -> m a

-- | The <a>routeLocal</a> function is the same as <a>route</a>, except it
--   doesn't change the request's context path. This is useful if you want
--   to route to a particular handler but you want that handler to receive
--   the <a>rqPathInfo</a> as it is.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import <a>Snap.Test</a>
--   ghci&gt; :{
--   ghci| let handler = do r &lt;- <a>getRequest</a>
--   ghci|                  <a>writeBS</a> $ "rqContextPath: " &lt;&gt; <a>rqContextPath</a> r &lt;&gt; "\n"
--   ghci|                  <a>writeBS</a> $ "rqPathInfo: " &lt;&gt; <a>rqPathInfo</a> r &lt;&gt; "\n"
--   ghci|                  <a>writeBS</a> $ "rqParams: " &lt;&gt; (B8.pack . show $ <a>rqParams</a> r)
--   ghci| :}
--   ghci&gt; <a>runHandler</a> (<a>get</a> "/foo/bar" M.empty) (<a>routeLocal</a> [("foo", handler)])
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 05:17:28 GMT
--   
--   rqContextPath: /
--   rqPathInfo: foo/bar
--   ghci&gt; <a>runHandler</a> (<a>get</a> "/foo/bar" M.empty) (<a>routeLocal</a> [("foo/:bar", handler)])
--   [...]
--   
--   rqContextPath: /
--   rqPathInfo: foo/bar
--   rqParams: fromList [("bar",["bar"])]
--   </pre>
routeLocal :: MonadSnap m => [(ByteString, m a)] -> m a

-- | Grabs the <a>Request</a> object out of the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> . <a>rqURI</a> =&lt;&lt; <a>getRequest</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 07:51:54 GMT
--   
--   /foo/bar
--   </pre>
getRequest :: MonadSnap m => m Request

-- | Grabs something out of the <a>Request</a> object, using the given
--   projection function. See <tt>gets</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> =&lt;&lt; <a>getsRequest</a> <a>rqURI</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 07:51:54 GMT
--   
--   /foo/bar
--   </pre>
getsRequest :: MonadSnap m => (Request -> a) -> m a

-- | Grabs the <a>Response</a> object out of the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> . <a>rspStatusReason</a> =&lt;&lt; <a>getResponse</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Sat, 02 Aug 2014 15:06:00 GMT
--   
--   OK
--   </pre>
getResponse :: MonadSnap m => m Response

-- | Grabs something out of the <a>Response</a> object, using the given
--   projection function. See <tt>gets</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> =&lt;&lt; <a>getsResponse</a> <a>rspStatusReason</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 13:35:45 GMT
--   
--   OK
--   </pre>
getsResponse :: MonadSnap m => (Response -> a) -> m a

-- | Puts a new <a>Request</a> object into the <a>Snap</a> monad. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; :{
--   ghci| let hndlr = do rq &lt;- T.buildRequest (T.get "/bar/foo" M.empty)
--   ghci|                <a>putRequest</a> rq
--   ghci|                uri' &lt;- <a>getsRequest</a> <a>rqURI</a>
--   ghci|                <a>writeBS</a> uri'
--   ghci| :}
--   ghci&gt; T.runHandler (T.get "/foo/bar" M.empty) hndlr
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:13:46 GMT
--   
--   /bar/foo
--   </pre>
putRequest :: MonadSnap m => Request -> m ()

-- | Puts a new <a>Response</a> object into the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let rsp = <a>setResponseCode</a> 404 <a>emptyResponse</a>
--   ghci&gt; let req = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler req (<a>putResponse</a> rsp)
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Wed, 06 Aug 2014 13:59:58 GMT
--   </pre>
putResponse :: MonadSnap m => Response -> m ()

-- | Modifies the <a>Request</a> object stored in a <a>Snap</a> monad.
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; r' &lt;- T.buildRequest $ T.get "/bar/foo" M.empty
--   ghci&gt; T.runHandler r (<a>modifyRequest</a> (const r') &gt;&gt; <a>getsRequest</a> <a>rqURI</a> &gt;&gt;= <a>writeBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:24:25 GMT
--   
--   /bar/foo
--   </pre>
modifyRequest :: MonadSnap m => (Request -> Request) -> m ()

-- | Modifes the <a>Response</a> object stored in a <a>Snap</a> monad.
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>modifyResponse</a> $ <a>setResponseCode</a> 404)
--   HTTP/1.1 404 Not Found
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:27:11 GMT
--   </pre>
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()

-- | Runs a <a>Snap</a> action with a locally-modified <a>Request</a> state
--   object. The <a>Request</a> object in the Snap monad state after the
--   call to localRequest will be unchanged. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; r' &lt;- T.buildRequest $ T.get "/bar/foo" M.empty
--   ghci&gt; let printRqURI = <a>getsRequest</a> <a>rqURI</a> &gt;&gt;= <a>writeBS</a> &gt;&gt; <a>writeBS</a> "\n"
--   ghci&gt; T.runHandler r (printRqURI &gt;&gt; <a>localRequest</a> (const r') printRqURI)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:34:12 GMT
--   
--   /foo/bar
--   /bar/foo
--   </pre>
localRequest :: MonadSnap m => (Request -> Request) -> m a -> m a

-- | Fetches the <a>Request</a> from state and hands it to the given
--   action. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import <a>Control.Monad.IO.Class</a>
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let h = <a>withRequest</a> (\rq -&gt; <a>liftIO</a> (T.requestToString rq) &gt;&gt;= <a>writeBS</a>)
--   ghci&gt; 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
--   </pre>
withRequest :: MonadSnap m => (Request -> m a) -> m a

-- | Fetches the <a>Response</a> from state and hands it to the given
--   action. Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>withResponse</a> $ <a>writeBS</a> . <a>rspStatusReason</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 15:48:45 GMT
--   
--   OK
--   </pre>
withResponse :: MonadSnap m => (Response -> m a) -> m a

-- | Log an error message in the <a>Snap</a> monad.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; <a>runSnap</a> (<a>logError</a> "fatal error!") (<tt>error</tt> . B8.unpack) undefined undefined
--   *** Exception: fatal error!
--   </pre>
logError :: MonadSnap m => ByteString -> m ()

-- | 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
--   <a>skipToEof</a>) before rethrowing the exception. If you used
--   <a>terminateConnection</a>, 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import qualified <a>Data.ByteString.Lazy</a> as L
--   ghci&gt; import <a>Data.Char</a> (toUpper)
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; :{
--   ghci| let f s = do u &lt;- Streams.map (B8.map toUpper) s
--   ghci|              l &lt;- Streams.toList u
--   ghci|              return $ L.fromChunks l
--   ghci| :}
--   ghci&gt; T.runHandler r (<a>runRequestBody</a> f &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:48:40 GMT
--   
--   SOME TEXT
--   </pre>
runRequestBody :: MonadSnap m => (InputStream ByteString -> IO a) -> m a

-- | Returns the request body as a lazy bytestring. /Note that the request
--   is not actually provided lazily!/
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; T.runHandler r (<a>readRequestBody</a> 2048 &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:08:44 GMT
--   
--   some text
--   </pre>
--   
--   <i>Since: 0.6</i>
readRequestBody :: MonadSnap m => Word64 -> m ByteString

-- | Normally Snap is careful to ensure that the request body is fully
--   consumed after your web handler runs, but before the <a>Response</a>
--   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 <a>finishWith</a>. Make sure you set any
--   content types, headers, cookies, etc. before you call this function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; import <a>Data.Char</a> (toUpper)
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.put "/foo" "text/plain" "some text"
--   ghci&gt; let f = Streams.map (B8.map toUpper)
--   ghci&gt; T.runHandler r (<a>transformRequestBody</a> f &gt;&gt; <a>readRequestBody</a> 2048 &gt;&gt;= <a>writeLBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 20:30:15 GMT
--   
--   SOME TEXT
--   </pre>
transformRequestBody :: (InputStream ByteString -> IO (InputStream ByteString)) -> Snap ()

-- | Contains all of the information about an incoming HTTP request.
data Request

-- | Represents an HTTP response.
data Response

-- | A key-value map that represents a collection of HTTP header fields.
--   Keys are case-insensitive.
data Headers

-- | A typeclass for datatypes which contain HTTP headers.
class HasHeaders a

-- | Modify the datatype's headers.
updateHeaders :: HasHeaders a => (Headers -> Headers) -> a -> a

-- | Retrieve the headers from a datatype that has headers.
headers :: HasHeaders a => a -> Headers

-- | A type alias for the HTTP parameters mapping. Each parameter key maps
--   to a list of <a>ByteString</a> values; if a parameter is specified
--   multiple times (e.g.: "<tt>GET /foo?param=bar1&amp;param=bar2</tt>"),
--   looking up "<tt>param</tt>" in the mapping will give you <tt>["bar1",
--   "bar2"]</tt>.
type Params = Map ByteString [ByteString]

-- | Enumerates the HTTP method values (see
--   <a>http://tools.ietf.org/html/rfc2068.html#section-5.1.1</a>).
data Method
GET :: Method
HEAD :: Method
POST :: Method
PUT :: Method
DELETE :: Method
TRACE :: Method
OPTIONS :: Method
CONNECT :: Method
PATCH :: Method
Method :: ByteString -> Method

-- | A datatype representing an HTTP cookie.
data Cookie
Cookie :: !ByteString -> !ByteString -> !Maybe UTCTime -> !Maybe ByteString -> !Maybe ByteString -> !Bool -> !Bool -> Cookie

-- | The name of the cookie.
[cookieName] :: Cookie -> !ByteString

-- | The cookie's string value.
[cookieValue] :: Cookie -> !ByteString

-- | The cookie's expiration value, if it has one.
[cookieExpires] :: Cookie -> !Maybe UTCTime

-- | The cookie's "domain" value, if it has one.
[cookieDomain] :: Cookie -> !Maybe ByteString

-- | The cookie path.
[cookiePath] :: Cookie -> !Maybe ByteString

-- | Tag as secure cookie?
[cookieSecure] :: Cookie -> !Bool

-- | HTTP only?
[cookieHttpOnly] :: Cookie -> !Bool

-- | Represents a (major, minor) version of the HTTP protocol.
type HttpVersion = (Int, Int)

-- | Adds a header key-value-pair to the <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, the new value is appended to
--   the headers list.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>addHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; <a>addHeader</a> "Host" "127.0.0.1" it
--   H {unH = [("host","localhost,127.0.0.1")]}
--   </pre>
addHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Sets a header key-value-pair in a <a>HasHeaders</a> datatype. If a
--   header with the same name already exists, it is overwritten with the
--   new value.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = [("host","localhost")]}
--   ghci&gt; setHeader "Host" "127.0.0.1" it
--   H {unH = [("host","127.0.0.1")]}
--   </pre>
setHeader :: HasHeaders a => CI ByteString -> ByteString -> a -> a

-- | Gets a header value out of a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>getHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   Just "localhost"
--   </pre>
getHeader :: HasHeaders a => CI ByteString -> a -> Maybe ByteString

-- | Lists all the headers out of a <a>HasHeaders</a> datatype. If many
--   headers came in with the same name, they will be catenated together.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>listHeaders</a> $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   [("host","localhost")]
--   </pre>
listHeaders :: HasHeaders a => a -> [(CI ByteString, ByteString)]

-- | Clears a header value from a <a>HasHeaders</a> datatype.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import qualified <a>Snap.Types.Headers</a> as H
--   ghci&gt; <a>deleteHeader</a> "Host" $ <a>setHeader</a> "Host" "localhost" H.<tt>empty</tt>
--   H {unH = []}
--   </pre>
deleteHeader :: HasHeaders a => CI ByteString -> a -> a

-- | Modifies the <a>Request</a> in the state to set the
--   <tt>rqRemoteAddr</tt> 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.
ipHeaderFilter :: MonadSnap m => m ()

-- | Modifies the <a>Request</a> in the state to set the
--   <tt>rqRemoteAddr</tt> 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.
ipHeaderFilter' :: MonadSnap m => CI ByteString -> m ()

-- | Contains all HTTP <a>Headers</a> associated with this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqHeaders `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   H {unH = [("host","localhost")]}
--   </pre>
rqHeaders :: Request -> Headers

-- | The server name of the request, as it came in from the request's
--   <tt>Host:</tt> header.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.get "/foo/bar" M.empty
--   ghci|         T.setHeader "host" "example.com"
--   ghci| :}
--   ghci&gt; rqHostName rq
--   "example.com"
--   </pre>
rqHostName :: Request -> ByteString

-- | The remote IP address.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
rqClientAddr :: Request -> ByteString

-- | The remote TCP port number.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqClientPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "60000"
--   </pre>
rqClientPort :: Request -> Int

-- | The local IP address for this request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerAddr `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "127.0.0.1"
--   </pre>
rqServerAddr :: Request -> ByteString

-- | 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqServerPort `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   8080
--   </pre>
rqServerPort :: Request -> Int

-- | Returns the HTTP server's idea of its local hostname, including port.
--   This is as configured with the <tt>Config</tt> object at startup.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqLocalHostname `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "localhost"
--   </pre>
rqLocalHostname :: Request -> ByteString

-- | Returns <tt>True</tt> if this is an HTTPS session.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqIsSecure `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   False
--   </pre>
rqIsSecure :: Request -> Bool

-- | Returns the <tt>Content-Length</tt> of the HTTP request body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContentLength `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   Nothing
--   </pre>
rqContentLength :: Request -> Maybe Word64

-- | Returns the HTTP request method.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqMethod `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   GET
--   </pre>
rqMethod :: Request -> Method

-- | Returns the HTTP version used by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqVersion `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   (1,1)
--   </pre>
rqVersion :: Request -> HttpVersion

-- | Returns a list of the cookies that came in from the HTTP request
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqCookies `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   []
--   </pre>
rqCookies :: Request -> [Cookie]

-- | Handlers can be hung on a <tt>URI</tt> "entry point"; this is called
--   the "context path". If a handler is hung on the context path
--   <tt>"/foo/"</tt>, and you request <tt>"/foo/bar"</tt>, the value of
--   <a>rqPathInfo</a> will be <tt>"bar"</tt>.
--   
--   The following identity holds:
--   
--   <pre>
--   rqURI r == S.concat [ rqContextPath r
--                       , rqPathInfo r
--                       , let q = rqQueryString r
--                         in if S.null q
--                              then ""
--                              else S.append "?" q
--                       ]
--   </pre>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqPathInfo `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
rqPathInfo :: Request -> ByteString

-- | The "context path" of the request; catenating <a>rqContextPath</a>,
--   and <a>rqPathInfo</a> should get you back to the original <a>rqURI</a>
--   (ignoring query strings). The <a>rqContextPath</a> always begins and
--   ends with a slash (<tt>"/"</tt>) character, and represents the path
--   (relative to your component/snaplet) you took to get to your handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqContextPath `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "/"
--   </pre>
rqContextPath :: Request -> ByteString

-- | Returns the <tt>URI</tt> requested by the client.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rqURI `fmap` T.buildRequest (T.get "/foo/bar" M.empty)
--   "foo/bar"
--   </pre>
rqURI :: Request -> ByteString

-- | Returns the HTTP query string for this <a>Request</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; rq &lt;- T.buildRequest (T.get "/foo/bar" (M.fromList [("name", ["value"])]))
--   ghci&gt; rqQueryString rq
--   "name=value"
--   </pre>
rqQueryString :: Request -> ByteString

-- | Returns the parameters mapping for this <a>Request</a>. "Parameters"
--   are automatically decoded from the URI's query string and
--   <tt>POST</tt> body and entered into this mapping. The <a>rqParams</a>
--   value is thus a union of <a>rqQueryParams</a> and <a>rqPostParams</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqParams rq
--   fromList [("baz",["qux","quux"])]
--   </pre>
rqParams :: Request -> Params

-- | The parameter mapping decoded from the URI's query string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqQueryParams rq
--   fromList [("baz",["quux"])]
--   </pre>
rqQueryParams :: Request -> Params

-- | The parameter mapping decoded from the POST body. Note that Snap only
--   auto-decodes POST request bodies when the request's
--   <tt>Content-Type</tt> is <tt>application/x-www-form-urlencoded</tt>.
--   For <tt>multipart/form-data</tt> use <a>handleFileUploads</a> to
--   decode the POST request and fill this mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; rqPostParams rq
--   fromList [("baz",["qux"])]
--   </pre>
rqPostParams :: Request -> Params

-- | 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 <tt>Content-Type</tt> is
--   <tt>application/x-www-form-urlencoded</tt>). Parameter values can be
--   modified within handlers using "rqModifyParams".
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParam</a> "baz" rq
--   Just ["qux","quux"]
--   </pre>
rqParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the POST
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqPostParam</a> "baz" rq
--   Just ["qux"]
--   </pre>
rqPostParam :: ByteString -> Request -> Maybe [ByteString]

-- | Looks up the value(s) for the given named parameter in the query
--   parameters mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqQueryParam</a> "baz" rq
--   Just ["quux"]
--   </pre>
rqQueryParam :: ByteString -> Request -> Maybe [ByteString]

-- | See <a>rqParam</a>. Looks up a value for the given named parameter in
--   the <a>Request</a>. If more than one value was entered for the given
--   parameter name, <a>getParam</a> gloms the values together with
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 12:57:20 GMT
--   
--   Just "bar"
--   </pre>
getParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqPostParam</a>. Looks up a value for the given named parameter
--   in the POST form parameters mapping in <a>Request</a>. If more than
--   one value was entered for the given parameter name,
--   <a>getPostParam</a> gloms the values together with:
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getPostParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:01:04 GMT
--   
--   Just "bar"
--   </pre>
getPostParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqQueryParam</a>. Looks up a value for the given named
--   parameter in the query string parameters mapping in <a>Request</a>. If
--   more than one value was entered for the given parameter name,
--   <a>getQueryParam</a> gloms the values together with
--   <tt><a>intercalate</a> " "</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" M.empty &gt;&gt; T.setQueryStringRaw "foo=bar&amp;foo=baz"
--   ghci&gt; T.runHandler r (<a>getQueryParam</a> "foo" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:06:50 GMT
--   
--   Just "bar baz"
--   </pre>
getQueryParam :: MonadSnap m => ByteString -> m (Maybe ByteString)

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.get "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:02:54 GMT
--   
--   fromList [("foo",["bar"])]
--   </pre>
getParams :: MonadSnap m => m Params

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" $ M.fromList [("foo", ["bar"])]
--   ghci&gt; T.runHandler r (<a>getPostParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:04:34 GMT
--   
--   fromList [("foo",["bar"])]
--   </pre>
getPostParams :: MonadSnap m => m Params

-- | See <a>rqParams</a>. Convenience function to return <a>Params</a> from
--   the <a>Request</a> inside of a <a>MonadSnap</a> instance.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let r = T.postUrlEncoded "/foo/bar" M.empty &gt;&gt; T.setQueryStringRaw "foo=bar&amp;foo=baz"
--   ghci&gt; T.runHandler r (<a>getQueryParams</a> &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Mon, 11 Aug 2014 13:10:17 GMT
--   
--   fromList [("foo",["bar","baz"])]
--   </pre>
getQueryParams :: MonadSnap m => m Params

-- | Modifies the parameters mapping (which is a <tt>Map ByteString
--   ByteString</tt>) in a <a>Request</a> using the given function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqModifyParams</a> (M.delete "baz") rq
--   fromList []
--   </pre>
rqModifyParams :: (Params -> Params) -> Request -> Request

-- | Writes a key-value pair to the parameters mapping within the given
--   request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| rq &lt;- T.buildRequest $ do
--   ghci|         T.postUrlEncoded "/foo/bar" $ M.fromList [("baz", ["qux"])]
--   ghci|         T.setQueryStringRaw "baz=quux"
--   ghci| :}
--   ghci&gt; <a>rqParams</a> rq
--   fromList [("baz",["qux","quux"])]
--   ghci&gt; <a>rqParams</a> $ <a>rqSetParam</a> "baz" ["corge"] rq
--   fromList [("baz", ["corge"])]
--   </pre>
rqSetParam :: ByteString -> [ByteString] -> Request -> Request

-- | See <a>rqClientAddr</a>.

-- | <i>Deprecated: (snap-core &gt;= 1.0.0.0) please use
--   <a>rqClientAddr</a>, this will be removed in 1.1.*</i>
rqRemoteAddr :: Request -> ByteString

-- | See <a>rqClientPort</a>.

-- | <i>Deprecated: (snap-core &gt;= 1.0.0.0) please use
--   <a>rqClientPort</a>, this will be removed in 1.1.*</i>
rqRemotePort :: Request -> Int

-- | An empty <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
emptyResponse :: Response

-- | Sets the HTTP response code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setResponseCode 404 <a>emptyResponse</a>
--   HTTP/1.1 404 Not Found
--   </pre>
setResponseCode :: Int -> Response -> Response

-- | Sets the HTTP response status. Note: normally you would use
--   <a>setResponseCode</a> unless you needed a custom response
--   explanation.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setResponseStatus 500 "Internal Server Error" <a>emptyResponse</a>
--   HTTP/1.1 500 Internal Server Error
--   </pre>
setResponseStatus :: Int -> ByteString -> Response -> Response

-- | Returns the HTTP status code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatus <a>emptyResponse</a>
--   200
--   </pre>
rspStatus :: Response -> Int

-- | Returns the HTTP status explanation string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; rspStatusReason <a>emptyResponse</a>
--   <a>OK</a>
--   </pre>
rspStatusReason :: Response -> ByteString

-- | Sets the <tt>Content-Type</tt> in the <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; setContentType "text/html" <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   content-type: text/html
--   </pre>
setContentType :: ByteString -> Response -> Response

-- | Adds an HTTP <a>Cookie</a> to <a>Response</a> headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   </pre>
addResponseCookie :: Cookie -> Response -> Response

-- | Gets an HTTP <a>Cookie</a> with the given name from <a>Response</a>
--   headers.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>getResponseCookie</a> "cookie-name" <a>emptyResponse</a>
--   Nothing
--   </pre>
getResponseCookie :: ByteString -> Response -> Maybe Cookie

-- | Returns a list of <a>Cookie</a>s present in <a>Response</a>
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>getResponseCookies</a> <a>emptyResponse</a>
--   []
--   </pre>
getResponseCookies :: Response -> [Cookie]

-- | Deletes an HTTP <a>Cookie</a> from the <a>Response</a> headers. Please
--   note this does not necessarily erase the cookie from the client
--   browser.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" $ <a>deleteResponseCookie</a> "name" rsp
--   Nothing
--   </pre>
deleteResponseCookie :: ByteString -> Response -> Response

-- | Modifies an HTTP <a>Cookie</a> with given name in <a>Response</a>
--   headers. Nothing will happen if a matching <a>Cookie</a> can not be
--   found in <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let rsp    = <a>addResponseCookie</a> cookie <a>emptyResponse</a>
--   ghci&gt; <a>getResponseCookie</a> "name" rsp
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   ghci&gt; let f ck@(<a>Cookie</a> { cookieName = name }) = ck { cookieName = name &lt;&gt; "'"}
--   ghci&gt; let rsp' = <a>modifyResponseCookie</a> "name" f rsp
--   ghci&gt; <a>getResponseCookie</a> "name'" rsp'
--   Just (Cookie {cookieName = "name'", ...})
--   ghci&gt; <a>getResponseCookie</a> "name" rsp'
--   Just (Cookie {cookieName = "name", ...})
--   </pre>
modifyResponseCookie :: ByteString -> (Cookie -> Cookie) -> Response -> Response

-- | Expire given <a>Cookie</a> in client's browser.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; let cookie = Cookie "name" "" Nothing (Just "/subsite") Nothing True False
--   ghci&gt; T.runHandler r (<a>expireCookie</a> cookie)
--   HTTP/1.1 200 OK
--   set-cookie: name=; path=/subsite; expires=Sat, 24 Dec 1994 06:28:16 GMT; Secure
--   server: Snap/test
--   
--   date: Thu, 07 Aug 2014 12:21:27 GMT
--   ghci&gt; let cookie = Cookie "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r2 = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>getCookie</a> "name" &gt;&gt;= maybe (return ()) <a>expireCookie</a>)
--   HTTP/1.1 200 OK
--   set-cookie: name=; expires=Sat, 24 Dec 1994 06:28:16 GMT
--   server: Snap/test
--   </pre>
expireCookie :: MonadSnap m => Cookie -> m ()

-- | Gets the HTTP <a>Cookie</a> with the specified name.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>getCookie</a> "name" &gt;&gt;= <a>writeBS</a> . B8.pack . show)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 12:16:58 GMT
--   
--   Just (Cookie {cookieName = "name", cookieValue = "value", ...})
--   </pre>
getCookie :: MonadSnap m => ByteString -> m (Maybe Cookie)

-- | Gets the HTTP <a>Cookie</a> with the specified name and decodes it. If
--   the decoding fails, the handler calls pass.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; let r = T.get "/foo/bar" M.empty &gt;&gt; T.addCookies [cookie]
--   ghci&gt; T.runHandler r (<a>readCookie</a> "name" &gt;&gt;= <a>writeBS</a>)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 07 Aug 2014 12:20:09 GMT
--   
--   value
--   </pre>
readCookie :: (MonadSnap m, Readable a) => ByteString -> m a

-- | A note here: if you want to set the <tt>Content-Length</tt> for the
--   response, Snap forces you to do it with this function rather than by
--   setting it in the headers; the <tt>Content-Length</tt> in the headers
--   will be ignored.
--   
--   The reason for this is that Snap needs to look up the value of
--   <tt>Content-Length</tt> 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 <tt>Connection:
--   close</tt>. For HTTP/1.1 clients, Snap will switch to the chunked
--   transfer encoding if <tt>Content-Length</tt> is not specified.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; setContentLength 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   Content-Length: 400
--   </pre>
setContentLength :: Word64 -> Response -> Response

-- | Removes any <tt>Content-Length</tt> set in the <a>Response</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; clearContentLength $ <a>setContentLength</a> 400 <a>emptyResponse</a>
--   HTTP/1.1 200 OK
--   </pre>
clearContentLength :: Response -> Response

-- | Performs a redirect by setting the <tt>Location</tt> header to the
--   given target URL/path and the status code to 302 in the
--   <a>Response</a> object stored in a <a>Snap</a> monad. Note that the
--   target URL is not validated in any way. Consider using
--   <a>redirect'</a> instead, which allows you to choose the correct
--   status code.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>redirect</a> "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
--   </pre>
redirect :: MonadSnap m => ByteString -> m a

-- | Performs a redirect by setting the <tt>Location</tt> header to the
--   given target URL/path and the status code (should be one of 301, 302,
--   303 or 307) in the <a>Response</a> object stored in a <a>Snap</a>
--   monad. Note that the target URL is not validated in any way.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>redirect'</a> "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
--   </pre>
redirect' :: MonadSnap m => ByteString -> Int -> m a

-- | Sets an HTTP response body to the given stream procedure.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   </pre>
setResponseBody :: (OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Modifies a response body.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.<a>byteString</a> "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; r
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   ghci&gt; :{
--   ghci| let r' = <a>modifyResponseBody</a>
--   ghci|          (f out -&gt; do
--   ghci|              out' &lt;- f out
--   ghci|              Streams.write (Just $ Builder.<a>byteString</a> "\nBye, world!") out'
--   ghci|              return out') r
--   ghci| :}
--   ghci&gt; r'
--   HTTP/1.1 200 OK
--   
--   Hello, world!
--   Bye, world!
--   </pre>
modifyResponseBody :: ((OutputStream Builder -> IO (OutputStream Builder)) -> OutputStream Builder -> IO (OutputStream Builder)) -> Response -> Response

-- | Run the given stream procedure, adding its output to the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as B
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; :{
--   ghci| let f str = do {
--   ghci|   Streams.write (Just $ B.byteString "Hello, streams world") str;
--   ghci|   return str }
--   ghci| :}
--   ghci&gt; T.runHandler r (<a>addToOutput</a> f)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:55:47 GMT
--   
--   Hello, streams world
--   </pre>
addToOutput :: MonadSnap m => (OutputStream Builder -> IO (OutputStream Builder)) -> m ()

-- | Adds the given <a>Builder</a> to the body of the <a>Response</a>
--   stored in the | <a>Snap</a> monad state.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as B
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBuilder</a> $ B.byteString "Hello, world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:33:33 GMT
--   
--   Hello, world
--   </pre>
writeBuilder :: MonadSnap m => Builder -> m ()

-- | Adds the given strict <a>ByteString</a> to the body of the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeBS</a> "Hello, bytestring world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:34:27 GMT
--   
--   Hello, bytestring world
--   </pre>
writeBS :: MonadSnap m => ByteString -> m ()

-- | Adds the given lazy <a>Text</a> to the body of the <a>Response</a>
--   stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeLazyText</a> "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
--   </pre>
writeLazyText :: MonadSnap m => Text -> m ()

-- | Adds the given strict <a>Text</a> to the body of the <a>Response</a>
--   stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeText</a> "Hello, text world")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Wed, 06 Aug 2014 17:36:38 GMT
--   
--   Hello, text world
--   </pre>
writeText :: MonadSnap m => Text -> m ()

-- | Adds the given lazy <a>ByteString</a> to the body of the
--   <a>Response</a> stored in the <a>Snap</a> monad state.
--   
--   Warning: This function is intentionally non-strict. If any pure
--   exceptions are raised by the expression creating the
--   <a>ByteString</a>, the exception won't actually be raised within the
--   Snap handler.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>writeLBS</a> "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
--   </pre>
writeLBS :: MonadSnap m => ByteString -> m ()

-- | Sets the output to be the contents of the specified file.
--   
--   Calling <a>sendFile</a> will overwrite any output queued to be sent in
--   the <a>Response</a>. If the response body is not modified after the
--   call to <a>sendFile</a>, Snap will use the efficient
--   <tt>sendfile()</tt> system call on platforms that support it.
--   
--   If the response body is modified (using <a>modifyResponseBody</a>),
--   the file will be read using <tt>mmap()</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; <tt>writeFile</tt> "/tmp/snap-file" "Hello, sendFile world"
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>sendFile</a> "/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
--   </pre>
sendFile :: MonadSnap m => FilePath -> m ()

-- | Sets the output to be the contents of the specified file, within the
--   given (start,end) range.
--   
--   Calling <a>sendFilePartial</a> will overwrite any output queued to be
--   sent in the <a>Response</a>. If the response body is not modified
--   after the call to <a>sendFilePartial</a>, Snap will use the efficient
--   <tt>sendfile()</tt> system call on platforms that support it.
--   
--   If the response body is modified (using <a>modifyResponseBody</a>),
--   the file will be read using <tt>mmap()</tt>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; <tt>writeFile</tt> "/tmp/snap-file" "Hello, sendFilePartial world"
--   ghci&gt; let r = T.get "/foo/bar" M.empty
--   ghci&gt; T.runHandler r (<a>sendFilePartial</a> "/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
--   </pre>
sendFilePartial :: MonadSnap m => FilePath -> (Word64, Word64) -> m ()

-- | Causes the handler thread to be killed <tt>n</tt> seconds from now.
setTimeout :: MonadSnap m => Int -> m ()

-- | Causes the handler thread to be killed at least <tt>n</tt> seconds
--   from now.
extendTimeout :: MonadSnap m => Int -> m ()

-- | Modifies the amount of time remaining before the request times out.
modifyTimeout :: MonadSnap m => (Int -> Int) -> m ()

-- | Returns an <a>IO</a> action which you can use to modify the timeout
--   value.
getTimeoutModifier :: MonadSnap m => m ((Int -> Int) -> IO ())

-- | Convert a <a>CTime</a> into an HTTP timestamp.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>formatHttpTime</a> . <a>fromIntegral</a> $ 10
--   "Thu, 01 Jan 1970 00:00:10 GMT"
--   </pre>
formatHttpTime :: CTime -> IO ByteString

-- | Converts an HTTP timestamp into a <a>CTime</a>.
--   
--   If the given time string is unparseable, this function will return 0.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>parseHttpTime</a> "Thu, 01 Jan 1970 00:00:10 GMT"
--   10
--   </pre>
parseHttpTime :: ByteString -> IO CTime

-- | Parse a string encoded in <tt>application/x-www-form-urlencoded</tt>
--   <a>format</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>parseUrlEncoded</a> "Name=John+Doe&amp;Name=Jane+Doe&amp;Age=23&amp;Formula=a+%2B+b+%3D%3D+13%25%21"
--   <a>fromList</a> [(<a>Age</a>,["23"]),(<a>Formula</a>,["a + b == 13%!"]),(<a>Name</a>,["John Doe","Jane Doe"])]
--   </pre>
parseUrlEncoded :: ByteString -> Map ByteString [ByteString]

-- | Like <a>printUrlEncoded</a>, but produces a <a>Builder</a> instead of
--   a <a>ByteString</a>. Useful for constructing a large string
--   efficiently in a single step.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import <a>Data.Map</a>
--   ghci&gt; import <a>Data.Monoid</a>
--   ghci&gt; import <a>Data.ByteString.Builder</a>
--   ghci&gt; let bldr = <a>buildUrlEncoded</a> (<a>fromList</a> [(<a>Name</a>, ["John Doe"]), (<a>Age</a>, ["23"])])
--   ghci&gt; <a>toLazyByteString</a> $ <a>byteString</a> "<a>http://example.com/script?"</a> &lt;&gt; bldr
--   "<a>http://example.com/script?Age=23&amp;Name=John+Doe"</a>
--   </pre>
buildUrlEncoded :: Map ByteString [ByteString] -> Builder

-- | Given a collection of key-value pairs with possibly duplicate keys
--   (represented as a <a>Map</a>), construct a string in
--   <tt>application/x-www-form-urlencoded</tt> format.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>printUrlEncoded</a> (<a>fromList</a> [(<a>Name</a>, ["John Doe"]), (<a>Age</a>, ["23"])])
--   "Age=23&amp;Name=John+Doe"
--   </pre>
printUrlEncoded :: Map ByteString [ByteString] -> ByteString

-- | URL-escape a string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>)
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>urlEncode</a> "1 attoparsec ~= 3 * 10^-2 meters"
--   "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   </pre>
urlEncode :: ByteString -> ByteString

-- | URL-escape a string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>) into a
--   <a>Builder</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import <a>Data.ByteString.Builder</a>
--   ghci&gt; <a>toLazyByteString</a> . <a>urlEncodeBuilder</a> $ "1 attoparsec ~= 3 * 10^-2 meters"
--   "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   </pre>
urlEncodeBuilder :: ByteString -> Builder

-- | Decode an URL-escaped string (see
--   <a>http://tools.ietf.org/html/rfc2396.html#section-2.4</a>)
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>urlDecode</a> "1+attoparsec+%7e%3d+3+*+10%5e-2+meters"
--   Just "1 attoparsec ~= 3 * 10^-2 meters"
--   </pre>
urlDecode :: ByteString -> Maybe ByteString


-- | Contains web handlers to serve files from a directory.
module Snap.Internal.Util.FileServe

-- | Gets a path from the <a>Request</a> using <a>rqPathInfo</a> 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; T.runHandler (T.get "/foo/bar" M.empty) (<a>getSafePath</a> &gt;&gt;= <a>writeBS</a> . B8.pack)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Fri, 08 Aug 2014 16:13:20 GMT
--   
--   foo/bar
--   ghci&gt; T.runHandler (T.get "/foo/../bar" M.empty) (<a>getSafePath</a> &gt;&gt;= <a>writeBS</a> . B8.pack)
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
getSafePath :: MonadSnap m => m FilePath

-- | A type alias for MIME type
type MimeMap = HashMap FilePath ByteString

-- | A type alias for dynamic handlers
type HandlerMap m = HashMap FilePath (FilePath -> m ())

-- | A collection of options for serving static files out of a directory.
data DirectoryConfig m
DirectoryConfig :: [FilePath] -> (FilePath -> m ()) -> HandlerMap m -> MimeMap -> (FilePath -> m ()) -> DirectoryConfig m

-- | Files to look for when a directory is requested (e.g., index.html)
[indexFiles] :: DirectoryConfig m -> [FilePath]

-- | Handler to generate a directory listing if there is no index.
[indexGenerator] :: DirectoryConfig m -> FilePath -> 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.
[dynamicHandlers] :: DirectoryConfig m -> HandlerMap m

-- | MIME type map to look up content types.
[mimeTypes] :: DirectoryConfig m -> MimeMap

-- | 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.
[preServeHook] :: DirectoryConfig m -> FilePath -> m ()

-- | A very simple configuration for directory serving. This configuration
--   uses built-in MIME types from <a>defaultMimeTypes</a>, and has no
--   index files, index generator, dynamic file handlers, or
--   <a>preServeHook</a>.
simpleDirectoryConfig :: MonadSnap m => DirectoryConfig m

-- | A reasonable default configuration for directory serving. This
--   configuration uses built-in MIME types from <a>defaultMimeTypes</a>,
--   serves common index files <tt>index.html</tt> and <tt>index.htm</tt>,
--   but does not autogenerate directory indexes, nor have any dynamic file
--   handlers. The <a>preServeHook</a> will not do anything.
defaultDirectoryConfig :: MonadSnap m => DirectoryConfig m

-- | A more elaborate configuration for file serving. This configuration
--   uses built-in MIME types from <a>defaultMimeTypes</a>, serves common
--   index files <tt>index.html</tt> and <tt>index.htm</tt>, and
--   autogenerates directory indexes with a Snap-like feel. It still has no
--   dynamic file handlers, nor <a>preServeHook</a>, which should be added
--   as needed.
--   
--   Files recognized as indexes include <tt>index.html</tt>,
--   <tt>index.htm</tt>, <tt>default.html</tt>, <tt>default.htm</tt>,
--   <tt>home.html</tt>
--   
--   Example of how the autogenerated directory index looks like:
--   
fancyDirectoryConfig :: MonadSnap m => DirectoryConfig 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 <a>MimeMap</a> 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 <a>DirectoryConfig</a>
--   
--   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.
defaultIndexGenerator :: MonadSnap m => MimeMap -> ByteString -> FilePath -> m ()

-- | The default set of mime type mappings we use when serving files. Its
--   value:
--   
--   <pre>
--   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"                                        ) ]
--   </pre>
defaultMimeTypes :: MimeMap

-- | Determine a given file's MIME type from its filename and the provided
--   MIME map.
fileType :: MimeMap -> FilePath -> ByteString

-- | Serves static files from a directory using the default configuration
--   as given in <a>defaultDirectoryConfig</a>.
serveDirectory :: MonadSnap m => FilePath -> m ()

-- | Serves static files from a directory. Configuration options are passed
--   in a <a>DirectoryConfig</a> that captures various choices about
--   desired behavior. The relative path given in <a>rqPathInfo</a> is
--   searched for a requested file, and the file is served with the
--   appropriate mime type if it is found. Absolute paths and "<tt>..</tt>"
--   are prohibited to prevent files from being served from outside the
--   sandbox.
serveDirectoryWith :: MonadSnap m => DirectoryConfig m -> FilePath -> 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 <i>not</i> pass
--   to the next handler). The path restrictions on <a>serveDirectory</a>
--   don't apply to this function since the path is not being supplied by
--   the user.
serveFile :: MonadSnap m => FilePath -> m ()

-- | Same as <a>serveFile</a>, with control over the MIME mapping used.
serveFileAs :: MonadSnap m => ByteString -> FilePath -> m ()
decodeFilePath :: FilePath -> IO Text
checkRangeReq :: MonadSnap m => Request -> FilePath -> Word64 -> m Bool


-- | The Snap.Test module contains primitives and combinators for testing
--   Snap applications.
module Snap.Test

-- | RequestBuilder is a monad transformer that allows you to conveniently
--   build a snap <a>Request</a> for testing.
data RequestBuilder m a

-- | A request body of type "<tt>multipart/form-data</tt>" consists of a
--   set of named form parameters, each of which can by either a list of
--   regular form values or a set of file uploads.
type MultipartParams = [(ByteString, MultipartParam)]

-- | A single "<tt>multipart/form-data</tt>" form parameter: either a list
--   of regular form values or a set of file uploads.
data MultipartParam

-- | a form variable consisting of the given <a>ByteString</a> values.
FormData :: [ByteString] -> MultipartParam

-- | a file upload consisting of the given <a>FileData</a> values.
Files :: [FileData] -> MultipartParam

-- | Represents a single file upload for the <a>MultipartParam</a>.
data FileData
FileData :: ByteString -> ByteString -> ByteString -> FileData

-- | the file's name
[fdFileName] :: FileData -> ByteString

-- | the file's content-type
[fdContentType] :: FileData -> ByteString

-- | the file contents
[fdContents] :: FileData -> ByteString

-- | The <a>RequestType</a> datatype enumerates the different kinds of HTTP
--   requests you can generate using the testing interface. Most users will
--   prefer to use the <a>get</a>, <a>postUrlEncoded</a>,
--   <a>postMultipart</a>, <a>put</a>, and <a>delete</a> convenience
--   functions.
data RequestType
GetRequest :: RequestType
RequestWithRawBody :: Method -> ByteString -> RequestType
MultipartPostRequest :: MultipartParams -> RequestType
UrlEncodedPostRequest :: Params -> RequestType
DeleteRequest :: RequestType

-- | Runs a <a>RequestBuilder</a>, producing the desired <a>Request</a>.
--   
--   N.B. <i>please</i> don't use the request you get here in a real Snap
--   application; things will probably break. Don't say you weren't warned
--   :-)
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" M.empty
--   GET /foo/bar HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
buildRequest :: MonadIO m => RequestBuilder m () -> m Request

-- | Given a web handler in the <a>Snap</a> monad, and a
--   <a>RequestBuilder</a> defining a test request, runs the handler,
--   producing an HTTP <a>Response</a>.
--   
--   This function will produce almost exactly the same output as running
--   the handler in a real server, except that chunked transfer encoding is
--   not applied, and the "Transfer-Encoding" header is not set (this makes
--   it easier to test response output).
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import <a>Snap.Core</a>
--   ghci&gt; <a>runHandler</a> (<a>get</a> "foo/bar" M.empty) (<a>writeBS</a> "Hello, world!")
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Thu, 17 Jul 2014 21:03:23 GMT
--   
--   Hello, world!
--   </pre>
runHandler :: MonadIO m => RequestBuilder m () -> Snap a -> m Response

-- | Given a web handler in some arbitrary <a>MonadSnap</a> monad, a
--   function specifying how to evaluate it within the context of the test
--   monad, and a <a>RequestBuilder</a> defining a test request, runs the
--   handler, producing an HTTP <a>Response</a>.
runHandlerM :: (MonadIO m, MonadSnap n) => (forall a. Request -> n a -> m Response) -> RequestBuilder m () -> n b -> m Response

-- | Given a web handler in the <a>Snap</a> monad, and a
--   <a>RequestBuilder</a> defining a test request, runs the handler and
--   returns the monadic value it produces.
--   
--   Throws an exception if the <a>Snap</a> handler early-terminates with
--   <a>finishWith</a> or <a>mzero</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import <a>Control.Monad</a>
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import <a>Snap.Core</a>
--   ghci&gt; <a>evalHandler</a> (<a>get</a> "foo/bar" M.empty) (<a>writeBS</a> "Hello, world!" &gt;&gt; return 42)
--   42
--   ghci&gt; <a>evalHandler</a> (<a>get</a> "foo/bar" M.empty) <a>mzero</a>
--   *** Exception: No handler for request: failure was pass
--   </pre>
evalHandler :: MonadIO m => RequestBuilder m () -> Snap a -> m a

-- | Given a web handler in some arbitrary <a>MonadSnap</a> monad, a
--   function specifying how to evaluate it within the context of the test
--   monad, and a <a>RequestBuilder</a> defining a test request, runs the
--   handler, returning the monadic value it produces.
--   
--   Throws an exception if the <a>Snap</a> handler early-terminates with
--   <a>finishWith</a> or <a>mzero</a>.
evalHandlerM :: (MonadIO m, MonadSnap n) => (forall a. Request -> n a -> m a) -> RequestBuilder m () -> n b -> m b

-- | Builds an HTTP "GET" request with the given query parameters.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" (M.fromList [("param0", ["baz", "quux"])])
--   GET /foo/bar?param0=baz&amp;param0=quux HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   params: param0: ["baz","quux"]
--   </pre>
get :: MonadIO m => ByteString -> Params -> RequestBuilder m ()
head :: [a] -> a

-- | Builds an HTTP "POST" request with the given form parameters, using
--   the "application/x-www-form-urlencoded" MIME type.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>postUrlEncoded</a> "/foo/bar" (M.fromList [("param0", ["baz", "quux"])])
--   POST /foo/bar HTTP/1.1
--   content-type: application/x-www-form-urlencoded
--   content-length: 22
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=22
--   params: param0: ["baz","quux"]
--   </pre>
postUrlEncoded :: MonadIO m => ByteString -> Params -> RequestBuilder m ()

-- | Builds an HTTP "POST" request with the given form parameters, using
--   the "form-data/multipart" MIME type.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>buildRequest</a> $ <a>postMultipart</a> "/foo/bar" [("param0", FormData ["baz", "quux"])]
--   POST /foo/bar HTTP/1.1
--   content-type: multipart/form-data; boundary=snap-boundary-572334111ec0c05ad4812481e8585dfa
--   content-length: 406
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=406
--   </pre>
postMultipart :: MonadIO m => ByteString -> MultipartParams -> RequestBuilder m ()

-- | Builds an HTTP "PUT" request.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>buildRequest</a> $ <a>put</a> "/foo/bar" "text/plain" "some text"
--   PUT /foo/bar HTTP/1.1
--   content-type: text/plain
--   content-length: 9
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9
--   </pre>
put :: MonadIO m => ByteString -> ByteString -> ByteString -> RequestBuilder m ()

-- | Builds a "raw" HTTP "POST" request, with the given MIME type and body
--   contents.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>buildRequest</a> $ <a>postRaw</a> "/foo/bar" "text/plain" "some text"
--   POST /foo/bar HTTP/1.1
--   content-type: text/plain
--   content-length: 9
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9
--   </pre>
postRaw :: MonadIO m => ByteString -> ByteString -> ByteString -> RequestBuilder m ()

-- | Builds an HTTP "DELETE" request with the given query parameters.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>delete</a> "/foo/bar" M.empty
--   DELETE /foo/bar HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
delete :: MonadIO m => ByteString -> Params -> RequestBuilder m ()

-- | Adds the given header to the request being built.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| <a>buildRequest</a> $ do <a>get</a> "/foo/bar" M.empty
--   ghci|                   <a>addHeader</a> "Accept" "text/html"
--   ghci|                   <a>addHeader</a> "Accept" "text/plain"
--   ghci| :}
--   GET /foo/bar HTTP/1.1
--   accept: text/html,text/plain
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
addHeader :: Monad m => CI ByteString -> ByteString -> RequestBuilder m ()

-- | Sets the request's <tt>content-type</tt> to the given MIME type.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>put</a> "/foo/bar" "text/html" "some text" &gt;&gt; <a>setContentType</a> "text/plain"
--   PUT /foo/bar HTTP/1.1
--   content-type: text/plain
--   content-length: 9
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=9
--   </pre>
setContentType :: Monad m => ByteString -> RequestBuilder m ()

-- | Sets the given header in the request being built, overwriting any
--   header with the same name already present.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; :{
--   ghci| <a>buildRequest</a> $ do get "/foo/bar" M.empty
--   ghci|                   <a>setHeader</a> "Accept" "text/html"
--   ghci|                   <a>setHeader</a> "Accept" "text/plain"
--   ghci| :}
--   GET /foo/bar HTTP/1.1
--   accept: text/plain
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
setHeader :: Monad m => CI ByteString -> ByteString -> RequestBuilder m ()

-- | Adds the given cookies to the request being built.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import <a>Snap.Core</a>
--   ghci&gt; let cookie = <a>Cookie</a> "name" "value" Nothing Nothing Nothing False False
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" M.empty &gt;&gt; <a>addCookies</a> [cookie]
--   GET /foo/bar HTTP/1.1
--   cookie: name=value
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   cookies: Cookie {cookieName = "name", cookieValue = "value", ...}
--   </pre>
addCookies :: Monad m => [Cookie] -> RequestBuilder m ()

-- | Sets the test request's http version
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>delete</a> "/foo/bar" M.empty &gt;&gt; <a>setHttpVersion</a> (1,0)
--   DELETE /foo/bar HTTP/1.0
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
setHttpVersion :: Monad m => (Int, Int) -> RequestBuilder m ()

-- | Escapes the given parameter mapping and sets it as the request's query
--   string.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" M.empty &gt;&gt; <a>setQueryString</a> (M.fromList [("param0", ["baz"]), ("param1", ["qux"])])
--   GET /foo/bar?param0=baz&amp;param1=qux HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   params: param0: ["baz"], param1: ["qux"]
--   </pre>
setQueryString :: Monad m => Params -> RequestBuilder m ()

-- | Sets the request's query string to be the raw bytestring provided,
--   without any escaping or other interpretation. Most users should
--   instead choose the <a>setQueryString</a> function, which takes a
--   parameter mapping.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" M.empty &gt;&gt; <a>setQueryStringRaw</a> "param0=baz&amp;param1=qux"
--   GET /foo/bar?param0=baz&amp;param1=qux HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   params: param0: ["baz"], param1: ["qux"]
--   </pre>
setQueryStringRaw :: Monad m => ByteString -> RequestBuilder m ()

-- | Sets the request's path. The path provided must begin with a
--   "<tt>/</tt>" and must <i>not</i> contain a query string; if you want
--   to provide a query string in your test request, you must use
--   <a>setQueryString</a> or <a>setQueryStringRaw</a>. Note that
--   <a>rqContextPath</a> is never set by any <a>RequestBuilder</a>
--   function.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>get</a> "/foo/bar" M.empty &gt;&gt; <a>setRequestPath</a> "/bar/foo"
--   GET /bar/foo HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
setRequestPath :: Monad m => ByteString -> RequestBuilder m ()

-- | Sets the type of the <a>Request</a> being built.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>delete</a> "/foo/bar" M.empty &gt;&gt; <a>setRequestType</a> GetRequest
--   GET /foo/bar HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a
--   </pre>
setRequestType :: MonadIO m => RequestType -> RequestBuilder m ()

-- | Controls whether the test request being generated appears to be an
--   https request or not.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; <a>buildRequest</a> $ <a>delete</a> "/foo/bar" M.empty &gt;&gt; <a>setSecure</a> True
--   DELETE /foo/bar HTTP/1.1
--   host: localhost
--   
--   sn="localhost" c=127.0.0.1:60000 s=127.0.0.1:8080 ctx=/ clen=n/a secure
--   </pre>
setSecure :: Monad m => Bool -> RequestBuilder m ()

-- | Given a <a>Response</a>, assert that its HTTP status code is 200
--   (success).
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Test.HUnit</a> as T
--   ghci&gt; let test = T.runTestTT . T.TestCase
--   ghci&gt; test $ <a>assertSuccess</a> <a>emptyResponse</a>
--   Cases: 1  Tried: 1  Errors: 0  Failures: 0
--   Counts {cases = 1, tried = 1, errors = 0, failures = 0}
--   ghci&gt; test $ <a>assertSuccess</a> (<a>setResponseStatus</a> 500 "Internal Server Error" <a>emptyResponse</a>)
--   ### Failure:
--   Expected success (200) but got (500)
--   expected: 200
--    but got: 500
--   Cases: 1  Tried: 1  Errors: 0  Failures: 1
--   Counts {cases = 1, tried = 1, errors = 0, failures = 1}
--   </pre>
assertSuccess :: Response -> Assertion

-- | Given a <a>Response</a>, assert that its HTTP status code is 404 (Not
--   Found).
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>assert404</a> $ <a>setResponseStatus</a> 404 "Not Found" <a>emptyResponse</a>
--   ghci&gt; <a>assert404</a> <a>emptyResponse</a>
--   *** Exception: HUnitFailure "Expected Not Found (404) but got (200)\nexpected: 404\n but got: 200"
--   </pre>
assert404 :: Response -> Assertion

-- | Given a <a>Response</a>, assert that its HTTP status code is between
--   300 and 399 (a redirect), and that the Location header of the
--   <a>Response</a> points to the specified URI.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; let r' = <a>setResponseStatus</a> 301 "Moved Permanently" <a>emptyResponse</a>
--   ghci&gt; let r  = <a>setHeader</a> "Location" "www.example.com" r'
--   ghci&gt; <a>assertRedirectTo</a> "www.example.com" r
--   ghci&gt; <a>assertRedirectTo</a> "www.example.com" <a>emptyResponse</a>
--   *** Exception: HUnitFailure "Expected redirect but got status code (200)"
--   </pre>
assertRedirectTo :: ByteString -> Response -> Assertion

-- | Given a <a>Response</a>, assert that its HTTP status code is between
--   300 and 399 (a redirect).
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; <a>assertRedirect</a> $ <a>setResponseStatus</a> 301 "Moved Permanently" <a>emptyResponse</a>
--   ghci&gt; <a>assertRedirect</a> <a>emptyResponse</a>
--   *** Exception: HUnitFailure "Expected redirect but got status code (200)"
--   </pre>
assertRedirect :: Response -> Assertion

-- | Given a <a>Response</a>, assert that its body matches the given
--   regular expression.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>System.IO.Streams</a> as Streams
--   ghci&gt; import qualified <a>Data.ByteString.Builder</a> as Builder
--   ghci&gt; :{
--   ghci| let r = <a>setResponseBody</a>
--   ghci|         (out -&gt; do
--   ghci|             Streams.write (Just $ Builder.byteString "Hello, world!") out
--   ghci|             return out)
--   ghci|         <a>emptyResponse</a>
--   ghci| :}
--   ghci&gt; <a>assertBodyContains</a> "^Hello" r
--   ghci&gt; <a>assertBodyContains</a> "Bye" r
--   *** Exception: HUnitFailure "Expected body to match regexp \"\"Bye\"\", but didn't"
--   </pre>
assertBodyContains :: ByteString -> Response -> Assertion

-- | Given a <a>Response</a>, return its body as a <a>ByteString</a>.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; <a>getResponseBody</a> <tt>emptyResponse</tt>
--   ""
--   </pre>
getResponseBody :: Response -> IO ByteString

-- | Converts the given <a>Request</a> to a bytestring.
--   
--   Since: 1.0.0.0
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; r &lt;- <a>buildRequest</a> $ get "/foo/bar" M.empty
--   ghci&gt; <a>requestToString</a> r
--   "GET /foo/bar HTTP/1.1\r\nhost: localhost\r\n\r\n"
--   </pre>
requestToString :: Request -> IO ByteString

-- | Converts the given <a>Response</a> to a bytestring.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; import <a>Snap.Core</a>
--   ghci&gt; <a>responseToString</a> <a>emptyResponse</a>
--   "HTTP/1.1 200 OK\r\n\r\n"
--   </pre>
responseToString :: Response -> IO ByteString


-- | Add <a>CORS</a> (cross-origin resource sharing) headers to a Snap
--   application. CORS headers can be added either conditionally or
--   unconditionally to the entire site, or you can apply CORS headers to a
--   single route.
--   
--   To use in a snaplet, simply use <tt>wrapSite</tt>:
--   
--   <pre>
--   wrapSite $ applyCORS defaultOptions
--   </pre>
module Snap.Util.CORS

-- | Apply CORS headers to a specific request. This is useful if you only
--   have a single action that needs CORS headers, and you don't want to
--   pay for conditional checks on every request.
--   
--   You should note that <a>applyCORS</a> needs to be used before you add
--   any <a>method</a> combinators. For example, the following won't do
--   what you want:
--   
--   <pre>
--   method POST $ applyCORS defaultOptions $ myHandler
--   </pre>
--   
--   This fails to work as CORS requires an <tt>OPTIONS</tt> request in the
--   preflighting stage, but this would get filtered out. Instead, use
--   
--   <pre>
--   applyCORS defaultOptions $ method POST $ myHandler
--   </pre>
applyCORS :: MonadSnap m => CORSOptions m -> m () -> m ()

-- | Specify the options to use when building CORS headers for a response.
--   Most of these options are <a>Handler</a> actions to allow you to
--   conditionally determine the setting of each header.
data CORSOptions m
CORSOptions :: m OriginList -> m Bool -> m (HashSet (CI ByteString)) -> m (HashSet HashableMethod) -> (HashSet ByteString -> m (HashSet ByteString)) -> CORSOptions m

-- | Which origins are allowed to make cross-origin requests.
[corsAllowOrigin] :: CORSOptions m -> m OriginList

-- | Whether or not to allow exposing the response when the omit
--   credentials flag is unset.
[corsAllowCredentials] :: CORSOptions m -> m Bool

-- | A list of headers that are exposed to clients. This allows clients to
--   read the values of these headers, if the response includes them.
[corsExposeHeaders] :: CORSOptions m -> m (HashSet (CI ByteString))

-- | A list of request methods that are allowed.
[corsAllowedMethods] :: CORSOptions m -> m (HashSet HashableMethod)

-- | An action to determine which of the request headers are allowed. This
--   action is supplied the parsed contents of
--   <tt>Access-Control-Request-Headers</tt>.
[corsAllowedHeaders] :: CORSOptions m -> HashSet ByteString -> m (HashSet ByteString)

-- | Liberal default options. Specifies that:
--   
--   <ul>
--   <li>All origins may make cross-origin requests</li>
--   <li><tt>allow-credentials</tt> is true.</li>
--   <li>No extra headers beyond simple headers are exposed.</li>
--   <li><tt>GET</tt>, <tt>POST</tt>, <tt>PUT</tt>, <tt>DELETE</tt> and
--   <tt>HEAD</tt> are all allowed.</li>
--   <li>All request headers are allowed.</li>
--   </ul>
--   
--   All options are determined unconditionally.
defaultOptions :: Monad m => CORSOptions m

-- | Used to specify the contents of the
--   <tt>Access-Control-Allow-Origin</tt> header.
data OriginList

-- | Allow any origin to access this resource. Corresponds to
--   <tt>Access-Control-Allow-Origin: *</tt>
Everywhere :: OriginList

-- | Do not allow cross-origin requests
Nowhere :: OriginList

-- | Allow cross-origin requests from these origins.
Origins :: OriginSet -> OriginList

-- | A set of origins. RFC 6454 specifies that origins are a scheme, host
--   and port, so the <a>OriginSet</a> wrapper around a <a>HashSet</a>
--   ensures that each <a>URI</a> constists of nothing more than this.
data OriginSet
mkOriginSet :: [URI] -> OriginSet
origins :: OriginSet -> HashSet HashableURI

-- | A <tt>newtype</tt> over <a>URI</a> with a <a>Hashable</a> instance.
newtype HashableURI
HashableURI :: URI -> HashableURI
newtype HashableMethod
HashableMethod :: Method -> HashableMethod
instance GHC.Classes.Eq Snap.Util.CORS.HashableURI
instance GHC.Classes.Eq Snap.Util.CORS.HashableMethod
instance Data.Hashable.Class.Hashable Snap.Util.CORS.HashableMethod
instance GHC.Show.Show Snap.Util.CORS.HashableMethod
instance GHC.Show.Show Snap.Util.CORS.HashableURI
instance Data.Hashable.Class.Hashable Snap.Util.CORS.HashableURI


-- | Contains web handlers to serve files from a directory.
--   
--   Example usage:
--   
--   <pre>
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   module Main where
--   
--   import <a>Snap.Core</a>           (Snap, route)
--   import <a>Snap.Http.Server</a>    (quickHttpServe)
--   import <a>Snap.Util.FileServe</a>
--   
--   site :: Snap ()
--   site = <a>route</a>
--     [ ("/files",   <a>serveDirectory</a>                            "static")
--     , ("/simple",  <a>serveDirectoryWith</a> <a>simpleDirectoryConfig</a>  "static")
--     , ("/default", <a>serveDirectoryWith</a> <a>defaultDirectoryConfig</a> "static")
--     , ("/fancy",   <a>serveDirectoryWith</a> <a>fancyDirectoryConfig</a>   "static")
--     , ("/paper",   <a>serveFile</a>                                 "static/paper.pdf")
--     , ("/thesis",  <a>serveFileAs</a>        "application/pdf"      "static/thesis.pdf")
--     ]
--   
--   main :: IO ()
--   main = <a>quickHttpServe</a> site
--   </pre>
module Snap.Util.FileServe

-- | Gets a path from the <a>Request</a> using <a>rqPathInfo</a> 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:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; import qualified <a>Data.ByteString.Char8</a> as B8
--   ghci&gt; T.runHandler (T.get "/foo/bar" M.empty) (<a>getSafePath</a> &gt;&gt;= <a>writeBS</a> . B8.pack)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Fri, 08 Aug 2014 16:13:20 GMT
--   
--   foo/bar
--   ghci&gt; T.runHandler (T.get "/foo/../bar" M.empty) (<a>getSafePath</a> &gt;&gt;= <a>writeBS</a> . B8.pack)
--   HTTP/1.1 404 Not Found
--   ...
--   </pre>
getSafePath :: MonadSnap m => m FilePath

-- | A type alias for MIME type
type MimeMap = HashMap FilePath ByteString

-- | A type alias for dynamic handlers
type HandlerMap m = HashMap FilePath (FilePath -> m ())

-- | A collection of options for serving static files out of a directory.
data DirectoryConfig m
DirectoryConfig :: [FilePath] -> (FilePath -> m ()) -> HandlerMap m -> MimeMap -> (FilePath -> m ()) -> DirectoryConfig m

-- | Files to look for when a directory is requested (e.g., index.html)
[indexFiles] :: DirectoryConfig m -> [FilePath]

-- | Handler to generate a directory listing if there is no index.
[indexGenerator] :: DirectoryConfig m -> FilePath -> 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.
[dynamicHandlers] :: DirectoryConfig m -> HandlerMap m

-- | MIME type map to look up content types.
[mimeTypes] :: DirectoryConfig m -> MimeMap

-- | 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.
[preServeHook] :: DirectoryConfig m -> FilePath -> m ()

-- | A very simple configuration for directory serving. This configuration
--   uses built-in MIME types from <a>defaultMimeTypes</a>, and has no
--   index files, index generator, dynamic file handlers, or
--   <a>preServeHook</a>.
simpleDirectoryConfig :: MonadSnap m => DirectoryConfig m

-- | A reasonable default configuration for directory serving. This
--   configuration uses built-in MIME types from <a>defaultMimeTypes</a>,
--   serves common index files <tt>index.html</tt> and <tt>index.htm</tt>,
--   but does not autogenerate directory indexes, nor have any dynamic file
--   handlers. The <a>preServeHook</a> will not do anything.
defaultDirectoryConfig :: MonadSnap m => DirectoryConfig m

-- | A more elaborate configuration for file serving. This configuration
--   uses built-in MIME types from <a>defaultMimeTypes</a>, serves common
--   index files <tt>index.html</tt> and <tt>index.htm</tt>, and
--   autogenerates directory indexes with a Snap-like feel. It still has no
--   dynamic file handlers, nor <a>preServeHook</a>, which should be added
--   as needed.
--   
--   Files recognized as indexes include <tt>index.html</tt>,
--   <tt>index.htm</tt>, <tt>default.html</tt>, <tt>default.htm</tt>,
--   <tt>home.html</tt>
--   
--   Example of how the autogenerated directory index looks like:
--   
fancyDirectoryConfig :: MonadSnap m => DirectoryConfig 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 <a>MimeMap</a> 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 <a>DirectoryConfig</a>
--   
--   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.
defaultIndexGenerator :: MonadSnap m => MimeMap -> ByteString -> FilePath -> m ()

-- | The default set of mime type mappings we use when serving files. Its
--   value:
--   
--   <pre>
--   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"                                        ) ]
--   </pre>
defaultMimeTypes :: MimeMap

-- | Determine a given file's MIME type from its filename and the provided
--   MIME map.
fileType :: MimeMap -> FilePath -> ByteString

-- | Serves static files from a directory using the default configuration
--   as given in <a>defaultDirectoryConfig</a>.
serveDirectory :: MonadSnap m => FilePath -> m ()

-- | Serves static files from a directory. Configuration options are passed
--   in a <a>DirectoryConfig</a> that captures various choices about
--   desired behavior. The relative path given in <a>rqPathInfo</a> is
--   searched for a requested file, and the file is served with the
--   appropriate mime type if it is found. Absolute paths and "<tt>..</tt>"
--   are prohibited to prevent files from being served from outside the
--   sandbox.
serveDirectoryWith :: MonadSnap m => DirectoryConfig m -> FilePath -> 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 <i>not</i> pass
--   to the next handler). The path restrictions on <a>serveDirectory</a>
--   don't apply to this function since the path is not being supplied by
--   the user.
serveFile :: MonadSnap m => FilePath -> m ()

-- | Same as <a>serveFile</a>, with control over the MIME mapping used.
serveFileAs :: MonadSnap m => ByteString -> FilePath -> m ()


-- | This module contains primitives and helper functions for handling
--   requests with <tt>Content-type: multipart/form-data</tt>, i.e. HTML
--   forms and file uploads.
--   
--   Typically most users will want to use <a>handleFileUploads</a>, which
--   writes uploaded files to a temporary directory before sending them on
--   to a handler specified by the user.
--   
--   Users who wish to handle their file uploads differently can use the
--   lower-level interface called <a>handleMultipart</a>. That function
--   takes uploaded files and streams them to a consumer of the user's
--   choosing.
--   
--   Using these functions requires making "policy" decisions which Snap
--   can't really make for users, such as "what's the largest PDF file a
--   user is allowed to upload?" and "should we read form inputs into the
--   parameters mapping?". Policy is specified on a "global" basis (using
--   <a>UploadPolicy</a>), and on a per-file basis (using
--   <a>PartUploadPolicy</a>, which allows you to reject or limit the size
--   of certain uploaded <tt>Content-type</tt>s).
--   
--   Example usage:
--   
--   <pre>
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   module Main where
--   
--   import qualified Data.ByteString.Char8 as B8
--   import           Data.Functor          ((&lt;$&gt;))
--   import           <a>Snap.Core</a>             (<a>Snap</a>, <a>route</a>, <a>writeBS</a>)
--   import           Snap.Http.Server      (quickHttpServe)
--   import           <a>Snap.Util.FileUploads</a>
--   import           System.Posix          (FileOffset, fileSize, getFileStatus)
--   
--   uploadForm :: <a>Snap</a> ()
--   uploadForm = <a>writeBS</a> "&lt;form enctype=\"multipart/form-data\" action=\"/do-upload\" method=\"POST\"&gt;\
--       \&lt;input name=\"file\" type=\"file\" /&gt;\
--       \&lt;input type=\"submit\" value=\"Send File\" /&gt;\
--       \&lt;/form&gt;"
--   
--   getFileSize :: FilePath -&gt; IO FileOffset
--   getFileSize path = fileSize &lt;$&gt; getFileStatus path
--   
--   -- Upload handler that prints out the uploaded file's size.
--   doUpload :: <a>Snap</a> ()
--   doUpload = do
--     l &lt;- <a>handleFileUploads</a> "/tmp" <a>defaultUploadPolicy</a>
--          (const $ <a>allowWithMaximumSize</a> (<a>getMaximumFormInputSize</a> <a>defaultUploadPolicy</a>))
--          (\pinfo mbfname -&gt; do fsize &lt;- either (const $ return 0) getFileSize mbfname
--                                return (<a>partFileName</a> pinfo, fsize))
--     <tt>writeBS</tt> . B8.pack . show $ l
--   
--   site :: <a>Snap</a> ()
--   site = <a>route</a>
--     [ ("/upload",    uploadForm)
--     , ("/do-upload", doUpload)]
--   
--   main :: IO ()
--   main = quickHttpServe site
--   </pre>
module Snap.Util.FileUploads

-- | Processes form data and calls provided storage function on file parts.
--   
--   You can use this together with <a>withTemporaryStore</a>,
--   <a>storeAsLazyByteString</a> or provide your own callback to store
--   uploaded files.
--   
--   If you need to process uploaded file mime type or file name, do it in
--   the store callback function.
--   
--   See also <a>foldMultipart</a>.
--   
--   Example using with small files which can safely be stored in memory.
--   
--   <pre>
--   import qualified Data.ByteString.Lazy as Lazy
--   
--   handleSmallFiles :: MonadSnap m =&gt; [(ByteString, ByteString, Lazy.ByteString)]
--   handleSmallFiles = handleFormUploads uploadPolicy filePolicy store
--   
--     where
--       uploadPolicy = defaultUploadPolicy
--       filePolicy = setMaximumFileSize (64*1024)
--                    $ setMaximumNumberOfFiles 5
--                      defaultUploadPolicy
--       store partInfo stream = do
--          content &lt;- storeAsLazyByteString partInfo stream
--          let
--            fileName = partFileName partInfo
--            fileMime = partContentType partInfo
--          in (fileName, fileMime, content)
--   </pre>
handleFormUploads :: MonadSnap m => UploadPolicy -> FileUploadPolicy -> (PartInfo -> InputStream ByteString -> IO a) -> m ([FormParam], [FormFile a])

-- | Given an upload policy and a function to consume uploaded "parts",
--   consume a request body uploaded with <tt>Content-type:
--   multipart/form-data</tt>.
--   
--   If <a>setProcessFormInputs</a> is <a>True</a>, then parts with
--   disposition <tt>form-data</tt> (a form parameter) will be processed
--   and returned as first element of resulting pair. Parts with other
--   disposition will be fed to <a>PartFold</a> handler.
--   
--   If <a>setProcessFormInputs</a> is <a>False</a>, then parts with any
--   disposition will be fed to <a>PartFold</a> handler and first element
--   of returned pair will be empty. In this case it is important that you
--   limit number of form inputs and sizes of inputs in your
--   <a>PartFold</a> handler to avoid common DOS attacks.
--   
--   Note: <i>THE REQUEST MUST BE CORRECTLY ENCODED</i>. If the request's
--   <tt>Content-type</tt> is not "<tt>multipart/formdata</tt>", this
--   function skips processing using <tt>pass</tt>.
--   
--   Most users will opt for the higher-level <a>handleFileUploads</a>,
--   which writes to temporary files, rather than <a>handleMultipart</a>.
--   This function should be chosen, however, if you need to stream
--   uploaded files directly to your own processing function: e.g. to a
--   database or a remote service via RPC.
--   
--   If the client's upload rate passes below the configured minimum (see
--   <a>setMinimumUploadRate</a> and <a>setMinimumUploadSeconds</a>), this
--   function terminates the connection. This setting is there to protect
--   the server against slowloris-style denial of service attacks.
--   
--   <i>Exceptions</i>
--   
--   If the given <a>UploadPolicy</a> stipulates that you wish form inputs
--   to be processed (using <a>setProcessFormInputs</a>), and a form input
--   exceeds the maximum allowable size or the form exceeds maximum number
--   of inputs, this function will throw a <a>PolicyViolationException</a>.
--   
--   If an uploaded part contains MIME headers longer than a fixed internal
--   threshold (currently 32KB), this function will throw a
--   <a>BadPartException</a>.
--   
--   <i>Since: 1.0.3.0</i>
foldMultipart :: MonadSnap m => UploadPolicy -> PartFold a -> a -> m ([FormParam], a)

-- | A type alias for a function that will process one of the parts of a
--   <tt>multipart/form-data</tt> HTTP request body with accumulator.
type PartFold a = PartInfo -> InputStream ByteString -> a -> IO a

-- | A form parameter name-value pair
type FormParam = (ByteString, ByteString)

-- | Contents of form field of type <tt>file</tt>
data FormFile a
FormFile :: !ByteString -> a -> FormFile a

-- | Name of a field
[formFileName] :: FormFile a -> !ByteString

-- | Result of storing file
[formFileValue] :: FormFile a -> a

-- | Stores file body in memory as Lazy ByteString.
storeAsLazyByteString :: InputStream ByteString -> IO ByteString

-- | Store files in a temporary directory, and clean up on function exit.
--   
--   Files are safe to move until function exists.
--   
--   If asynchronous exception is thrown during cleanup, temporary files
--   may remain.
--   
--   <pre>
--   uploadsHandler = withTemporaryStore "<i>var</i>tmp" "upload-" $ store -&gt; do
--       (inputs, files) &lt;- handleFormUploads defaultUploadpolicy
--                                            defaultFileUploadPolicy
--                                            (const store)
--       saveFiles files
--   </pre>
withTemporaryStore :: MonadSnap m => FilePath -> String -> ((InputStream ByteString -> IO FilePath) -> m a) -> m a

-- | Reads uploaded files into a temporary directory and calls a user
--   handler to process them.
--   
--   Note: <i>THE REQUEST MUST BE CORRECTLY ENCODED</i>. If the request's
--   <tt>Content-type</tt> is not "<tt>multipart/formdata</tt>", this
--   function skips processing using <tt>pass</tt>.
--   
--   Given a temporary directory, global and file-specific upload policies,
--   and a user handler, this function consumes a request body uploaded
--   with <tt>Content-type: multipart/form-data</tt>. Each file is read
--   into the temporary directory, and is then passed to the user handler.
--   After the user handler runs (but before the <tt>Response</tt> body is
--   streamed to the client), the files are deleted from disk; so if you
--   want to retain or use the uploaded files in the generated response,
--   you need to move or otherwise process them.
--   
--   The argument passed to the user handler is a tuple:
--   
--   <pre>
--   (PartInfo, Either PolicyViolationException FilePath)
--   </pre>
--   
--   The first half of this tuple is a <a>PartInfo</a>, which contains the
--   information the client browser sent about the given upload part (like
--   filename, content-type, etc). The second half of this tuple is an
--   <a>Either</a> stipulating that either:
--   
--   <ol>
--   <li>the file was rejected on a policy basis because of the provided
--   <a>PartUploadPolicy</a> handler</li>
--   <li>the file was accepted and exists at the given path.</li>
--   </ol>
--   
--   <i>Exceptions</i>
--   
--   If the client's upload rate passes below the configured minimum (see
--   <a>setMinimumUploadRate</a> and <a>setMinimumUploadSeconds</a>), this
--   function terminates the connection. This setting is there to protect
--   the server against slowloris-style denial of service attacks.
--   
--   If the given <a>UploadPolicy</a> stipulates that you wish form inputs
--   to be placed in the <a>rqParams</a> parameter map (using
--   <a>setProcessFormInputs</a>), and a form input exceeds the maximum
--   allowable size, this function will throw a
--   <a>PolicyViolationException</a>.
--   
--   If an uploaded part contains MIME headers longer than a fixed internal
--   threshold (currently 32KB), this function will throw a
--   <a>BadPartException</a>.
handleFileUploads :: MonadSnap m => FilePath -> UploadPolicy -> (PartInfo -> PartUploadPolicy) -> (PartInfo -> Either PolicyViolationException FilePath -> IO a) -> m [a]

-- | A variant of <a>foldMultipart</a> accumulating results into a list.
--   Also puts captured <a>FormParam</a>s into rqPostParams and rqParams
--   maps.
handleMultipart :: MonadSnap m => UploadPolicy -> PartProcessor a -> m [a]

-- | A type alias for a function that will process one of the parts of a
--   <tt>multipart/form-data</tt> HTTP request body without usinc
--   accumulator.
type PartProcessor a = PartInfo -> InputStream ByteString -> IO a

-- | <a>PartInfo</a> contains information about a "part" in a request
--   uploaded with <tt>Content-type: multipart/form-data</tt>.
data PartInfo

-- | Represents the disposition type specified via the
--   <tt>Content-Disposition</tt> header field. See <a>RFC 1806</a>.
data PartDisposition

-- | <tt>Content-Disposition: attachment</tt>.
DispositionAttachment :: PartDisposition

-- | <tt>Content-Disposition: file</tt>.
DispositionFile :: PartDisposition

-- | <tt>Content-Disposition: form-data</tt>.
DispositionFormData :: PartDisposition

-- | Any other value.
DispositionOther :: ByteString -> PartDisposition

-- | Field name associated with this part (i.e., the name specified with
--   <tt>&lt;input name="partFieldName" ...</tt>).
partFieldName :: PartInfo -> ByteString

-- | Name of the uploaded file.
partFileName :: PartInfo -> Maybe ByteString

-- | Content type of this part.
partContentType :: PartInfo -> ByteString

-- | Remaining headers associated with this part.
partHeaders :: PartInfo -> Headers

-- | Disposition type of this part. See <a>PartDisposition</a>.
partDisposition :: PartInfo -> PartDisposition

-- | <a>UploadPolicy</a> controls overall policy decisions relating to
--   <tt>multipart/form-data</tt> uploads, specifically:
--   
--   <ul>
--   <li>whether to treat parts without filenames as form input (reading
--   them into the <a>rqParams</a> map)</li>
--   <li>because form input is read into memory, the maximum size of a form
--   input read in this manner, and the maximum number of form inputs</li>
--   <li>the minimum upload rate a client must maintain before we kill the
--   connection; if very low-bitrate uploads were allowed then a Snap
--   server would be vulnerable to a trivial denial-of-service using a
--   "slowloris"-type attack</li>
--   <li>the minimum number of seconds which must elapse before we start
--   killing uploads for having too low an upload rate.</li>
--   <li>the amount of time we should wait before timing out the connection
--   whenever we receive input from the client.</li>
--   </ul>
data UploadPolicy

-- | A reasonable set of defaults for upload policy. The default policy is:
--   
--   <ul>
--   <li><i><tt>maximum form input size</tt></i> 128kB</li>
--   <li><i><tt>maximum number of form inputs</tt></i> 10</li>
--   <li><i><tt>minimum upload rate</tt></i> 1kB/s</li>
--   <li><i><tt>seconds before rate limiting kicks in</tt></i> 10</li>
--   <li><i><tt>inactivity timeout</tt></i> 20 seconds</li>
--   </ul>
defaultUploadPolicy :: UploadPolicy

-- | Does this upload policy stipulate that we want to treat parts without
--   filenames as form input?
doProcessFormInputs :: UploadPolicy -> Bool

-- | Set the upload policy for treating parts without filenames as form
--   input.
setProcessFormInputs :: Bool -> UploadPolicy -> UploadPolicy

-- | Get the maximum size of a form input which will be read into our
--   <a>rqParams</a> map.
getMaximumFormInputSize :: UploadPolicy -> Int64

-- | Set the maximum size of a form input which will be read into our
--   <a>rqParams</a> map.
setMaximumFormInputSize :: Int64 -> UploadPolicy -> UploadPolicy

-- | Get the maximum size of a form input which will be read into our
--   <a>rqParams</a> map.
getMaximumNumberOfFormInputs :: UploadPolicy -> Int

-- | Set the maximum size of a form input which will be read into our
--   <a>rqParams</a> map.
setMaximumNumberOfFormInputs :: Int -> UploadPolicy -> UploadPolicy

-- | Get the minimum rate (in <i>bytes/second</i>) a client must maintain
--   before we kill the connection.
getMinimumUploadRate :: UploadPolicy -> Double

-- | Set the minimum rate (in <i>bytes/second</i>) a client must maintain
--   before we kill the connection.
setMinimumUploadRate :: Double -> UploadPolicy -> UploadPolicy

-- | Get the amount of time which must elapse before we begin enforcing the
--   upload rate minimum
getMinimumUploadSeconds :: UploadPolicy -> Int

-- | Set the amount of time which must elapse before we begin enforcing the
--   upload rate minimum
setMinimumUploadSeconds :: Int -> UploadPolicy -> UploadPolicy

-- | Get the "upload timeout". Whenever input is received from the client,
--   the connection timeout is set this many seconds in the future.
getUploadTimeout :: UploadPolicy -> Int

-- | Set the upload timeout.
setUploadTimeout :: Int -> UploadPolicy -> UploadPolicy

-- | File upload policy, if any policy is violated then
--   <a>PolicyViolationException</a> is thrown
data FileUploadPolicy

-- | A default <a>FileUploadPolicy</a>
--   
--   <ul>
--   <li><i><tt>maximum file size</tt></i> 1MB</li>
--   <li><i><tt>maximum number of files</tt></i> 10</li>
--   <li><i><tt>skip files without name</tt></i> yes</li>
--   <li><i><tt>maximum size of skipped file</tt></i> 0</li>
--   </ul>
defaultFileUploadPolicy :: FileUploadPolicy

-- | Maximum size of single uploaded file.
setMaximumFileSize :: Int64 -> FileUploadPolicy -> FileUploadPolicy

-- | Maximum number of uploaded files.
setMaximumNumberOfFiles :: Int -> FileUploadPolicy -> FileUploadPolicy

-- | Skip files with empty file names.
--   
--   If set, parts without filenames will not be fed to storage function.
--   
--   HTML5 form data encoding standard states that form input fields of
--   type file, without value set, are encoded same way as if file with
--   empty body, empty file name, and type
--   <tt>application/octet-stream</tt> was set as value.
--   
--   You most likely want to use this with zero bytes allowed to avoid
--   storing such fields (see <a>setMaximumSkippedFileSize</a>).
--   
--   By default files without names are skipped.
--   
--   <i>Since: 1.0.3.0</i>
setSkipFilesWithoutNames :: Bool -> FileUploadPolicy -> FileUploadPolicy

-- | Maximum size of file without name which can be skipped.
--   
--   Ignored if <a>setSkipFilesWithoutNames</a> is <tt>False</tt>.
--   
--   If skipped file is larger than this setting then
--   <a>FileUploadException</a> is thrown.
--   
--   By default maximum file size is 0.
--   
--   <i>Since: 1.0.3.0</i>
setMaximumSkippedFileSize :: Int64 -> FileUploadPolicy -> FileUploadPolicy

-- | Upload policy can be set on an "general" basis (using
--   <a>UploadPolicy</a>), but handlers can also make policy decisions on
--   individual files/parts uploaded. For each part uploaded, handlers can
--   decide:
--   
--   <ul>
--   <li>whether to allow the file upload at all</li>
--   <li>the maximum size of uploaded files, if allowed</li>
--   </ul>
data PartUploadPolicy

-- | Disallows the file to be uploaded.
disallow :: PartUploadPolicy

-- | Allows the file to be uploaded, with maximum size <i>n</i> in bytes.
allowWithMaximumSize :: Int64 -> PartUploadPolicy

-- | All of the exceptions defined in this package inherit from
--   <a>FileUploadException</a>, so if you write
--   
--   <pre>
--   foo `catch` \(e :: FileUploadException) -&gt; ...
--   </pre>
--   
--   you can catch a <a>BadPartException</a>, a
--   <a>PolicyViolationException</a>, etc.
data FileUploadException

-- | Human-readable error message corresponding to the
--   <a>FileUploadException</a>.
fileUploadExceptionReason :: FileUploadException -> Text

-- | Thrown when a part is invalid in some way (e.g. the headers are too
--   large).
data BadPartException

-- | Human-readable error message corresponding to the
--   <a>BadPartException</a>.
badPartExceptionReason :: BadPartException -> Text

-- | Thrown when an <a>UploadPolicy</a> or <a>PartUploadPolicy</a> is
--   violated.
data PolicyViolationException

-- | Human-readable error message corresponding to the
--   <a>PolicyViolationException</a>.
policyViolationExceptionReason :: PolicyViolationException -> Text


-- | Helpers for running a <tt>Snap</tt> web handler with compression.
module Snap.Util.GZip

-- | Runs a <tt>Snap</tt> web handler with compression if available.
--   
--   If the client has indicated support for <tt>gzip</tt> or
--   <tt>deflate</tt> in its <tt>Accept-Encoding</tt> header, and the
--   <tt>Content-Type</tt> in the response is one of the following types:
--   
--   <ul>
--   <li><pre>application/x-javascript</pre></li>
--   <li><pre>application/json</pre></li>
--   <li><pre>text/css</pre></li>
--   <li><pre>text/html</pre></li>
--   <li><pre>text/javascript</pre></li>
--   <li><pre>text/plain</pre></li>
--   <li><pre>text/xml</pre></li>
--   <li><pre>application/x-font-truetype</pre></li>
--   </ul>
--   
--   Then the given handler's output stream will be compressed,
--   <tt>Content-Encoding</tt> will be set in the output headers, and the
--   <tt>Content-Length</tt> will be cleared if it was set. (We can't
--   process the stream in O(1) space if the length is known beforehand.)
--   
--   The wrapped handler will be run to completion, and then the
--   <tt>Response</tt> that's contained within the <tt>Snap</tt> monad
--   state will be passed to <a>finishWith</a> to prevent further
--   processing.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/" M.empty &gt;&gt; T.addHeader "Accept-Encoding" "gzip,deflate"
--   ghci&gt; let h = <a>modifyResponse</a> (<a>setContentType</a> "text/plain") &gt;&gt; <a>writeBS</a> "some text"
--   ghci&gt; T.runHandler r h
--   HTTP/1.1 200 OK
--   content-type: text/plain
--   server: Snap/test
--   date: Fri, 08 Aug 2014 15:40:45 GMT
--   
--   some text
--   ghci&gt; T.runHandler r (<a>withCompression</a> h)
--   HTTP/1.1 200 OK
--   content-type: text/plain
--   vary: Accept-Encoding
--   content-encoding: gzip
--   server: Snap/test
--   date: Fri, 08 Aug 2014 15:40:10 GMT
--   </pre>
withCompression :: MonadSnap m => m a -> m ()

-- | The same as <a>withCompression</a>, with control over which MIME types
--   to compress.
withCompression' :: MonadSnap m => Set ByteString -> m a -> m ()

-- | Turn off compression by setting "Content-Encoding: identity" in the
--   response headers. <a>withCompression</a> is a no-op when a
--   content-encoding is already set.
noCompression :: MonadSnap m => m ()

-- | Thrown when the 'Accept-Encoding' request header has invalid format.
data BadAcceptEncodingException
compressibleMimeTypes :: Set ByteString
instance GHC.Show.Show Snap.Util.GZip.BadAcceptEncodingException
instance GHC.Exception.Type.Exception Snap.Util.GZip.BadAcceptEncodingException


-- | This module provides facilities for patching incoming
--   <tt>Requests</tt> to correct the value of <a>rqClientAddr</a> if the
--   snap server is running behind a proxy.
--   
--   Example usage:
--   
--   <pre>
--   m :: Snap ()
--   m = undefined  -- code goes here
--   
--   applicationHandler :: Snap ()
--   applicationHandler = behindProxy X_Forwarded_For m
--   </pre>
module Snap.Util.Proxy

-- | What kind of proxy is this? Affects which headers <a>behindProxy</a>
--   pulls the original remote address from.
--   
--   Currently only proxy servers that send <tt>X-Forwarded-For</tt> or
--   <tt>Forwarded-For</tt> are supported.
data ProxyType

-- | no proxy, leave the request alone
NoProxy :: ProxyType

-- | Use the <tt>Forwarded-For</tt> or <tt>X-Forwarded-For</tt> header
X_Forwarded_For :: ProxyType

-- | Rewrite <a>rqClientAddr</a> if we're behind a proxy.
--   
--   Example:
--   
--   <pre>
--   ghci&gt; :set -XOverloadedStrings
--   ghci&gt; import qualified <a>Data.Map</a> as M
--   ghci&gt; import qualified <a>Snap.Test</a> as T
--   ghci&gt; let r = T.get "/foo" M.empty &gt;&gt; T.addHeader "X-Forwarded-For" "1.2.3.4"
--   ghci&gt; let h = <a>getsRequest</a> <a>rqClientAddr</a> &gt;&gt;= <a>writeBS</a>)
--   ghci&gt; T.runHandler r h
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Fri, 08 Aug 2014 14:32:29 GMT
--   
--   127.0.0.1
--   ghci&gt; T.runHandler r (<a>behindProxy</a> <a>X_Forwarded_For</a> h)
--   HTTP/1.1 200 OK
--   server: Snap/test
--   date: Fri, 08 Aug 2014 14:33:02 GMT
--   
--   1.2.3.4
--   </pre>
behindProxy :: MonadSnap m => ProxyType -> m a -> m a
instance GHC.Classes.Ord Snap.Util.Proxy.ProxyType
instance GHC.Classes.Eq Snap.Util.Proxy.ProxyType
instance GHC.Show.Show Snap.Util.Proxy.ProxyType
instance GHC.Read.Read Snap.Util.Proxy.ProxyType
