如何在 WAI/scotty 中记录整个 HTTP 请求?

问题描述 投票:0回答:3

我目前从 Network.Wai.Middleware.RequestLogger 运行中间件 logStdoutDev,但它只记录路径和 Accept 标头(可能还有其他标头)。我还想查看 POST 和 PUT 请求的正文。这个主体恰好是 json,所以只需将其打印到 stdout 就可以了。

我搜索了一个可以记录所有内容的 WAI 中间件,但没有找到。我对 WAI 内部结构了解不够,无法编写一些提取 POST 主体然后将其放回自己体内的东西,所以我希望现在能够避免这种学习曲线。

haskell
3个回答
4
投票

此功能由

wai-extra
包提供。

{-# LANGUAGE OverloadedStrings #-}

import Web.Scotty
import Network.HTTP.Types
import Network.Wai.Middleware.RequestLogger

main = scotty 3000 $ do
  middleware logStdoutDev
  get "/" $ do
    text "example"

输出示例:

Setting phasers to stun... (port 3000) (ctrl-c to quit)
GET /
  Accept: */*
  Status: 200 OK 0.000050947s

3
投票

WAI

Middleware
只是
Application
的转变:

type Middleware = Application -> Application

并且

Application
只是一个处理程序:

type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived

您需要做的就是定义处理程序,它将记录您想要的任何内容并将“实际工作”委托给下游:

-- note that this is equivalent to Application -> Application
logAllMiddleware :: Application -> Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
logAllMiddleware app req respond = do
    print . unpack . requestBody req
    app req respond

请记住,我编写此代码时没有访问 ghc。可能不完全正确。


0
投票

如果您需要记录更多请求/响应详细信息,您可以执行以下操作:

import Network.Wai.Middleware.RequestLogger.JSON
import Network.Wai.Middleware.RequestLogger


main = do
  logger <- liftIO $ mkRequestLogger defaultRequestLoggerSettings {
    outputFormat =  CustomOutputFormatWithDetailsAndHeaders formatAsJSONWithHeaders

...

scotty = do
  middleware logger            
  get "/" $ pure ()                                                      

输出示例:

{"request":{"body":"{\"message\":\"\",\"model\":\"ModelDeepSeekChat\",\"parentId\":null,\"reqConvId\":null}","durationMs":18.59,"headers":[["Host","10.0.2.2:3030"],["Accept-Encoding","gzip"],["Content-Length","75"],["Accept","application/json"],["Content-Type","application/json; charset=utf-8"]],"httpVersion":"1.1","method":"POST","path":"/api/replies","queryString":[],"remoteHost":{"hostAddress":"127.0.0.1","port":43838},"size":75},"response":{"body":null,"headers":[["Content-Type","application/json; charset=utf-8"]],"size":null,"status":200},"time":"28/Dec/2024:11:53:02 +0000"}

不幸的是,它不能很好地打印输出。

© www.soinside.com 2019 - 2024. All rights reserved.