6

我正在使用Scotty开发一个应用程序,当然还有WAI。我希望能够限制请求的大小,包括正文长度和标题。我怎样才能做到这一点?是否可以使用普通的 WAI 中间件来做到这一点?

4

3 回答 3

4

我不知道 Scotty 的详细信息,但当然可以设置一个 WAI 中间件来查看requestBodyLength,如果它太大,则返回适当的 413 状态代码页。您需要处理的一件事是上传正文是否使用分块编码发送,在这种情况下不存在内容长度。但这并不常见。您可以选择拒绝这些请求,或者添加代码来包装请求正文并在结果太大时返回错误(这就是 Yesod 所做的)。

于 2015-04-15T09:58:08.610 回答
1

标记的解决方案指向正确的方向,但如果您像我一样,您可能仍然难以明确地导出所需的完整代码。这是一个实现(感谢有经验的 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

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

于 2019-09-09T11:35:47.863 回答
1

wai-extra-3.1.1开始,上述代码已添加到Network.Wai.Middleware.RequestSizeLimit模块中,因此可以将其作为依赖项引入。

于 2021-10-19T13:34:50.520 回答