我想直接使用bloodhound或REST api使用Haskell向Amazon托管的elasticsearch服务器发送请求。
由于服务器具有基于 IAM 的访问策略,因此我需要对签名进行签名。为了对每个请求的签名进行签名,需要计算有效负载的哈希值。我不确定如何将RequestBody(分块与否(放入ByteString。
对于您的特定使用案例:在我看来,wreq
库已经支持 AWS IAM 签名(教程(,因此根据您的特定要求,最简单的方法是使用它/查看它是如何工作的。
看起来使用RequestBody
s 的最简单方法实际上可能只是编写一个函数来计算 6 种可能的RequestBody
中的每一种的签名,或者至少是您需要的签名,而无需尝试重用 http-client 的机器将 6 种中的任何一种转换为一个ByteString
。 这是一个特别有用的选项,因为看起来您可能需要对分块请求执行特殊操作。 对于RequestBody
可能是什么,只有几个选项(基于流的选项(似乎很难使用;这些通常也值得特殊对待(特别是因为,根据请求的创建者如何实现它们,我不清楚是否可以保证可以从它们中读取并让它们以后仍然工作(。 此源可能对此方法有用。
根据您使用 Haskell 的经验,流构造函数可能有点吓人。然而,这实际上还不错:扩展类型同义词会得到GivesPopper () = (IO ByteString -> IO ()) -> IO ()
。IO ByteString -> IO ()
函数是你可以提供的东西,它接受流区块的生产者(每个评估将产生更多的区块(,并用它做一些有用的事情---例如,将该区块写入IORef
的列表中,以便以后可以检查它。 如果在此函数上调用GivesPopper
,您将获得一个IO
操作,该操作以有用的生产者作为参数运行它。例如:
foo :: NeedsPopper ()
foo pop = do
chunk <- pop
if (chunk == "") then return ()
else BS.putStr chunk >> foo pop
将,当传递给GivesPopper ()
时,将流响应正文打印到 stdout。
如果你希望请求可以多次构建而没有问题(任何流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
功能用于其他用途,则可能无法很好地工作。 另请注意,这将写出分块请求的编码版本(例如"6rna bodyrn0rnrn"
(,这可能是您想要的,也可能不是您想要的。