如何在请求记录器中添加请求和响应正文的特定表示?我希望能够有一些typeclass
可以让我实现这种表示。在Network.Wai.Middleware.RequestLogger.JSON
我可以看到请求记录器是如何实现的。
formatAsJSONWithHeaders :: OutputFormatterWithDetailsAndHeaders
formatAsJSONWithHeaders date req status resSize duration reqBody res resHeaders =
toLogStr (encode $
object
[ "request" .= requestToJSON duration req reqBody
, "response" .= object
[ "status" .= statusCode status
, "size" .= resSize
, "headers" .= responseHeadersToJSON resHeaders
, "body" .=
if statusCode status >= 400
then Just . decodeUtf8With lenientDecode . toStrict . BB.toLazyByteString $ res
else Nothing
]
, "time" .= decodeUtf8With lenientDecode date
]) <> "\n"
requestToJSON :: NominalDiffTime -> Request -> [S8.ByteString] -> Value
requestToJSON duration req reqBody =
object
[ "method" .= decodeUtf8With lenientDecode (requestMethod req)
, "path" .= decodeUtf8With lenientDecode (rawPathInfo req)
, "queryString" .= map queryItemToJSON (queryString req)
, "durationMs" .= (readAsDouble . printf "%.2f" . rationalToDouble $ toRational duration * 1000)
, "size" .= requestBodyLengthToJSON (requestBodyLength req)
, "body" .= decodeUtf8With lenientDecode (S8.concat reqBody)
, "remoteHost" .= sockToJSON (remoteHost req)
, "httpVersion" .= httpVersionToJSON (httpVersion req)
, "headers" .= requestHeadersToJSON (requestHeaders req)
]
where
rationalToDouble :: Rational -> Double
rationalToDouble = fromRational
因此,如果我要收到请求:
new_user : { "email": "foo", "password": "bar" }
我只想通过电子邮件发送:
new_user : { "email": "foo", "password": "" }
我通过一些类型类来做到这一点:
class LogRepr body where
toLogRepr :: body -> Value -- Some monoidal text
instance LogRepr NewUser where
toLogRepr nu = object
[ "new_user" .=
object
[ "email" .= email nu
]
]
这将允许我轻松使用我不想修改其默认行为的类型的 toJSON 和 FromJSON。是否也可以修改它,以便当我的应用程序像“消息”字段或“活动”字段一样运行时,我可以添加一些任意上下文。