在httpclient中获取RequestBody

时间:2018-07-08 02:42:47

标签: haskell http-conduit

我想使用Haskell直接通过bloodhound或REST api将请求发送到Amazon托管的Elasticsearch服务器。

由于服务器具有基于IAM的访问策略,因此我需要签署signature。为了为每个单个请求签名,需要计算有效负载的哈希值。我不确定如何将RequestBody(分块与否)放入ByteString中。

1 个答案:

答案 0 :(得分:1)

对于您的特定用例:在我看来wreq库已经支持AWS IAM签名(tutorial),因此根据您的特定要求,最简单的选择是使用/看看它是如何工作的。

使用RequestBody s似乎最简单的方法实际上可能是编写一个函数来计算RequestBody的6种可能种类中的每一种或至少一种的签名。而不需要重用http-client的设备将6种设备中的任何一种转换为一个ByteString。这是一个特别有用的选项,因为看起来您可能需要对分块的请求执行特殊操作。 RequestBody可能只有几个选项,只有两个(基于流的选项)似乎很难使用。这些请求通常也应给予特殊待遇(特别是因为,根据请求创建者如何实现它们,我不确定是否可以保证可以从中读取信息并让它们以后继续工作)。 source可能对这种方法有用。

根据您对Haskell的经验,流构造器可能有些令人生畏。但是,实际上这还不错:扩展类型同义词会得到GivesPopper () = (IO ByteString -> IO ()) -> IO ()。您可以提供IO ByteString -> IO ()函数,该函数需要一个流块的生产者(每个评估将产生一个更大的块)并对其进行一些有用的操作-例如,将该块写入{ {1}},以便您以后进行检查。如果在此函数上调用IORef,将得到一个GivesPopper动作,该动作以有用的生产者作为参数来运行。例如:

IO

将传递给foo :: NeedsPopper () foo pop = do chunk <- pop if (chunk == "") then return () else BS.putStr chunk >> foo pop 时,将流式响应正文打印到stdout。

如果您希望可以多次构建请求而不会出现问题(任何流GivesPopper ()都必须可以多次调用,等等),并且您希望重用GivesPopper的内部响应呈现,您也许可以摆脱像这样的骇人听闻的东西:

http-client

getRequest :: Request -> IO BS.ByteString getRequest req = do (conn, out, inp) <- dummyConnection [] let req' = req { requestHeaders = (CI.mk "Expect", "100-continue") : requestHeaders req } (Just later) <- requestBuilder req' conn _ <- out later BS.concat <$> out 呈现http-client的唯一地方似乎是在Response中,并且在构建请求时,这将始终发送标头,我认为这不是您所需要的。想。 requestBuilder行从虚拟连接中清除标头+主体,并且由于给出了_ <- out,因此Expect: 100-continue应该再次将主体写入虚拟连接。请注意,这仅在可以多次构建响应而不会出现问题时有效。如果您的请求实际上期望使用later功能进行其他操作,则可能效果不佳。还要注意,这会写出分块请求的编码版本(例如continue),它可能不是您想要的。