我目前从 Network.Wai.Middleware.RequestLogger 运行中间件 logStdoutDev,但它只记录路径和 Accept 标头(可能还有其他标头)。我还想查看 POST 和 PUT 请求的正文。这个主体恰好是 json,所以只需将其打印到 stdout 就可以了。
我搜索了一个可以记录所有内容的 WAI 中间件,但没有找到。我对 WAI 内部结构了解不够,无法编写一些提取 POST 主体然后将其放回自己体内的东西,所以我希望现在能够避免这种学习曲线。
此功能由
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
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。可能不完全正确。
如果您需要记录更多请求/响应详细信息,您可以执行以下操作:
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"}
不幸的是,它不能很好地打印输出。