我想使用Haskell直接通过bloodhound或REST api将请求发送到Amazon托管的Elasticsearch服务器。
由于服务器具有基于IAM的访问策略,因此我需要签署signature。为了为每个单个请求签名,需要计算有效负载的哈希值。我不确定如何将RequestBody(分块与否)放入ByteString中。
答案 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
),它可能不是您想要的。