简体   繁体   English

如何在服务应用程序中访问原始请求体

[英]How to access raw request body in servant application

In a servant/wai application the request body can be obtained using a combinator eg ReqBody '[JSON] Book .在 servant/wai 应用程序中,请求主体可以使用组合器获得,例如ReqBody '[JSON] Book In this case the body is extracted as a value of type Book .在这种情况下,主体被提取为Book类型的值。 It is not clear how the raw request body can be accessed without converting it to a type.目前尚不清楚如何在不将其转换为类型的情况下访问原始请求主体。

The raw request body may be required to verify its signature.可能需要原始请求正文来验证其签名。 An example is in stripe webhooks (ie stripe.com) where the raw request body may be needed for verification.一个例子是 stripe webhooks(即 stripe.com),其中可能需要原始请求正文来进行验证。 There is a nice library on hackage.org (stripe-hs) that does this verification but does not explain how to obtain the raw request body. hackage.org (stripe-hs) 上有一个很好的库可以执行此验证,但没有解释如何获取原始请求主体。

I guess one way is through a middleware where the request body can be consumed once.我想一种方法是通过一个中间件,请求主体可以被消耗一次。 Is there any other way?还有别的办法吗?

What I ended up doing is to create a new data type data WebhookJSON and its corresponding MimeUnrender and MimeRender instances for this data type.我最终做的是为这个数据类型创建一个新的数据类型data WebhookJSON及其对应的 MimeUnrender 和 MimeRender 实例。 Just like its done for the JSON type.就像它为JSON类型所做的那样。 I used that data type in the combinators eg ReqBody '[WebhookJSON] ByteString .我在组合器中使用了该数据类型,例如ReqBody '[WebhookJSON] ByteString Hopefully (I haven't tested it yet), this is one way to gain access to the raw request body.希望(我还没有测试过),这是访问原始请求正文的一种方法。

To add onto 7puns' self-answer:添加到 7puns 的自我回答:

module JsonAsRawText where

import ClassyPrelude
import qualified Network.HTTP.Media               as M
import qualified Data.Text                        as TextS
import qualified Data.Text.Encoding               as TextS
import qualified Data.List.NonEmpty               as NE
import           Control.Arrow (left)
import Servant

data JsonAsRawText deriving Typeable

instance Accept JsonAsRawText where
  contentTypes _ =
    "application" M.// "json" M./: ("charset", "utf-8") NE.:|
    [ "application" M.// "json" ]

instance MimeUnrender JsonAsRawText TextS.Text where
  mimeUnrender _ = left show . TextS.decodeUtf8' . toStrict

It's worth noting that this bypasses a lot of Servant's wonderful automatic type machinery.值得注意的是,这绕过了很多 Servant 出色的自动机械。 It's really only useful when you absolutely need access to the raw body of a request of Content-Type: application/json as a string (to compute the security signature for an incoming webhook, for instance).仅当您绝对需要以字符串形式访问Content-Type: application/json请求的原始主体(例如,计算传入 webhook 的安全签名)时,它才有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM