如何在 WAI 中限制请求 body 和 headers 的大小?

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

我正在使用 Scotty and of course WAI 开发应用程序。我希望能够限制 body 长度和 headers 请求的大小。我怎样才能做到这一点?是否可以使用普通的 WAI 中间件来做到这一点?

我不知道 Scotty 的细节,但肯定可以设置一个 WAI 中间件来查看 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)。

标记的解决方案指向了正确的方向,但如果您像我一样,您可能仍然难以明确地导出所需的完整代码。下面是一个实现(感谢有经验的Haskell朋友的帮助):

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

中间件然后像这样在 scotty 的 do 块中运行

import Network.Wai.Middleware.RequestLogger (logStdout)

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

        get "/alive" $ do
            status Http.status200

        -- ...

如果您对如何推导它感到好奇(或者为什么我发现这并不过分琐碎),请考虑 Middleware

的别名
Application -> Application

其中 Application 本身是

的别名
Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived

因此,即使解决方案非常简洁,也有很多(精神上)解包的论据。

wai-extra-3.1.1 the code described above has been added to the Network.Wai.Middleware.RequestSizeLimit 模块开始,因此它可以作为依赖项引入。