Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I limit size of request body and headers in WAI?

I am developing an application using Scotty and of course WAI. I would like to be able to limit the size of requests, both for body length and for headers. How can I do that? Is it possible to do it using a plain WAI middleware ?

like image 789
insitu Avatar asked Apr 15 '15 07:04

insitu


3 Answers

I don't know details of Scotty, but it's certainly possible to set up a WAI middleware that will look at the requestBodyLength and, if it's too large, return an appropriate 413 status code page. One thing you'd need to deal with is if the upload body is sent with chunked encoding, in which case no content-length is present. but that's uncommon. You have the option of either rejecting those requests, or adding code to wrap the request body and return an error if it turns out to be too large (that's what Yesod does).

like image 95
Michael Snoyman Avatar answered Nov 03 '22 01:11

Michael Snoyman


The marked solution points in the correct direction, but if you're like me you might still struggle to explicitely derive the full code needed. Here is an implementation (thanks to the help of an experienced Haskell friend):

import qualified Network.HTTP.Types as Http
import qualified Network.Wai as Wai

limitRequestSize :: Wai.Middleware
limitRequestSize app req respond = do
    case Wai.requestBodyLength req of
        Wai.KnownLength len -> do
            if len > maxLen
                then respond $ Wai.responseBuilder Http.status413 [] mempty
                else app req respond

        Wai.ChunkedBody ->
            respond $ Wai.responseBuilder Http.status411 [] mempty
    where
        maxLen = 50*1000 -- 50kB

The middleware then just runs in scotty's do block like this

import Network.Wai.Middleware.RequestLogger (logStdout)

main :: IO ()
main = do
    scotty 3000 $ do
        middleware logStdout
        middleware limitRequestSize

        get "/alive" $ do
            status Http.status200

        -- ...

If you're curious as to how to derive it (or why I found this not overly trivial), consider that Middleware is an alias for

Application -> Application

where Application itself is an alias for

Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived

Hence there are quite a bunch of arguments to (mentally) unpack, even if the solution is pretty terse.

like image 41
instant Avatar answered Nov 03 '22 00:11

instant


As of wai-extra-3.1.1 the code described above has been added to the Network.Wai.Middleware.RequestSizeLimit module, so it can just be pulled in as a dependency.

like image 24
Profpatsch Avatar answered Nov 03 '22 00:11

Profpatsch