Safe Haskell | None |
---|
This module contains primitives and helper functions for handling
requests with Content-type: multipart/form-data
, i.e. HTML forms and file
uploads.
Typically most users will want to use handleFileUploads
, 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 streaming Iteratee
interface called handleMultipart
. That
function takes uploaded files and streams them to an Iteratee
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
UploadPolicy
), and on a per-file basis (using PartUploadPolicy
, which
allows you to reject or limit the size of certain uploaded
Content-type
s).
- handleFileUploads :: MonadSnap m => FilePath -> UploadPolicy -> (PartInfo -> PartUploadPolicy) -> ([(PartInfo, Either PolicyViolationException FilePath)] -> m a) -> m a
- handleMultipart :: MonadSnap m => UploadPolicy -> (PartInfo -> Iteratee ByteString IO a) -> m [a]
- data PartInfo = PartInfo {}
- data UploadPolicy
- defaultUploadPolicy :: UploadPolicy
- doProcessFormInputs :: UploadPolicy -> Bool
- setProcessFormInputs :: Bool -> UploadPolicy -> UploadPolicy
- getMaximumFormInputSize :: UploadPolicy -> Int64
- setMaximumFormInputSize :: Int64 -> UploadPolicy -> UploadPolicy
- getMaximumNumberOfFormInputs :: UploadPolicy -> Int
- setMaximumNumberOfFormInputs :: Int -> UploadPolicy -> UploadPolicy
- getMinimumUploadRate :: UploadPolicy -> Double
- setMinimumUploadRate :: Double -> UploadPolicy -> UploadPolicy
- getMinimumUploadSeconds :: UploadPolicy -> Int
- setMinimumUploadSeconds :: Int -> UploadPolicy -> UploadPolicy
- getUploadTimeout :: UploadPolicy -> Int
- setUploadTimeout :: Int -> UploadPolicy -> UploadPolicy
- data PartUploadPolicy
- disallow :: PartUploadPolicy
- allowWithMaximumSize :: Int64 -> PartUploadPolicy
- data FileUploadException
- fileUploadExceptionReason :: FileUploadException -> Text
- data BadPartException
- badPartExceptionReason :: BadPartException -> Text
- data PolicyViolationException
- policyViolationExceptionReason :: PolicyViolationException -> Text
Functions
:: MonadSnap m | |
=> FilePath | temporary directory |
-> UploadPolicy | general upload policy |
-> (PartInfo -> PartUploadPolicy) | per-part upload policy |
-> ([(PartInfo, Either PolicyViolationException FilePath)] -> m a) | user handler (see function description) |
-> m a |
Reads uploaded files into a temporary directory and calls a user handler to process them.
Given a temporary directory, global and file-specific upload policies, and
a user handler, this function consumes a request body uploaded with
Content-type: multipart/form-data
. Each file is read into the temporary
directory, and then a list of the uploaded files is passed to the user
handler. After the user handler runs (but before the Response
body
Enumerator
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 would need to move or otherwise process them.
The argument passed to the user handler is a list of:
(PartInfo, Either PolicyViolationException FilePath)
The first half of this tuple is a PartInfo
, 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 Either
stipulating that either:
- the file was rejected on a policy basis because of the provided
PartUploadPolicy
handler - the file was accepted and exists at the given path.
If the request's Content-type
was not "multipart/formdata
", this
function skips processing using pass
.
If the client's upload rate passes below the configured minimum (see
setMinimumUploadRate
and setMinimumUploadSeconds
), this function
terminates the connection. This setting is there to protect the server
against slowloris-style denial of service attacks.
If the given UploadPolicy
stipulates that you wish form inputs to be
placed in the rqParams
parameter map (using setProcessFormInputs
), and
a form input exceeds the maximum allowable size, this function will throw a
PolicyViolationException
.
If an uploaded part contains MIME headers longer than a fixed internal
threshold (currently 32KB), this function will throw a BadPartException
.
:: MonadSnap m | |
=> UploadPolicy | global upload policy |
-> (PartInfo -> Iteratee ByteString IO a) | part processor |
-> m [a] |
Given an upload policy and a function to consume uploaded "parts",
consume a request body uploaded with Content-type: multipart/form-data
.
Normally most users will want to use handleFileUploads
(which writes
uploaded files to a temporary directory and passes their names to a given
handler) rather than this function; the lower-level handleMultipart
function should be used if you want to stream uploaded files to your own
iteratee function.
If the request's Content-type
was not "multipart/formdata
", this
function skips processing using pass
.
If the client's upload rate passes below the configured minimum (see
setMinimumUploadRate
and setMinimumUploadSeconds
), this function
terminates the connection. This setting is there to protect the server
against slowloris-style denial of service attacks.
If the given UploadPolicy
stipulates that you wish form inputs to be
placed in the rqParams
parameter map (using setProcessFormInputs
), and
a form input exceeds the maximum allowable size, this function will throw a
PolicyViolationException
.
If an uploaded part contains MIME headers longer than a fixed internal
threshold (currently 32KB), this function will throw a BadPartException
.
Uploaded parts
PartInfo
contains information about a "part" in a request uploaded
with Content-type: multipart/form-data
.
PartInfo | |
|
Policy
General upload policy
data UploadPolicy Source
UploadPolicy
controls overall policy decisions relating to
multipart/form-data
uploads, specifically:
- whether to treat parts without filenames as form input (reading them into
the
rqParams
map) - 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
- 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
- the minimum number of seconds which must elapse before we start killing uploads for having too low an upload rate.
- the amount of time we should wait before timing out the connection whenever we receive input from the client.
defaultUploadPolicy :: UploadPolicySource
A reasonable set of defaults for upload policy. The default policy is:
maximum form input size
- 128kB
maximum number of form inputs
- 10
minimum upload rate
- 1kB/s
seconds before rate limiting kicks in
- 10
inactivity timeout
- 20 seconds
doProcessFormInputs :: UploadPolicy -> BoolSource
Does this upload policy stipulate that we want to treat parts without filenames as form input?
setProcessFormInputs :: Bool -> UploadPolicy -> UploadPolicySource
Set the upload policy for treating parts without filenames as form input.
getMaximumFormInputSize :: UploadPolicy -> Int64Source
Get the maximum size of a form input which will be read into our
rqParams
map.
setMaximumFormInputSize :: Int64 -> UploadPolicy -> UploadPolicySource
Set the maximum size of a form input which will be read into our
rqParams
map.
getMaximumNumberOfFormInputs :: UploadPolicy -> IntSource
Get the maximum size of a form input which will be read into our
rqParams
map.
setMaximumNumberOfFormInputs :: Int -> UploadPolicy -> UploadPolicySource
Set the maximum size of a form input which will be read into our
rqParams
map.
getMinimumUploadRate :: UploadPolicy -> DoubleSource
Get the minimum rate (in bytes\second/) a client must maintain before we kill the connection.
setMinimumUploadRate :: Double -> UploadPolicy -> UploadPolicySource
Set the minimum rate (in bytes\second/) a client must maintain before we kill the connection.
getMinimumUploadSeconds :: UploadPolicy -> IntSource
Get the amount of time which must elapse before we begin enforcing the upload rate minimum
setMinimumUploadSeconds :: Int -> UploadPolicy -> UploadPolicySource
Set the amount of time which must elapse before we begin enforcing the upload rate minimum
getUploadTimeout :: UploadPolicy -> IntSource
Get the "upload timeout". Whenever input is received from the client, the connection timeout is set this many seconds in the future.
setUploadTimeout :: Int -> UploadPolicy -> UploadPolicySource
Set the upload timeout.
Per-file upload policy
data PartUploadPolicy Source
Upload policy can be set on an "general" basis (using UploadPolicy
),
but handlers can also make policy decisions on individual files/parts
uploaded. For each part uploaded, handlers can decide:
- whether to allow the file upload at all
- the maximum size of uploaded files, if allowed
disallow :: PartUploadPolicySource
Disallows the file to be uploaded.
allowWithMaximumSize :: Int64 -> PartUploadPolicySource
Allows the file to be uploaded, with maximum size n.
Exceptions
data FileUploadException Source
All of the exceptions defined in this package inherit from
FileUploadException
, so if you write
foo `catch` \(e :: FileUploadException) -> ...
you can catch a BadPartException
, a PolicyViolationException
, etc.
data BadPartException Source