【问题标题】:Basic way of sending HTTP/POST in Haskell using http-conduit使用 http-conduit 在 Haskell 中发送 HTTP/POST 的基本方法
【发布时间】:2015-11-29 13:59:41
【问题描述】:

我正在尝试学习如何使用 Haskell 和 http-conduit 通过 HTTP/POST 发送简单的字符串(这样它也可以与 https 一起使用),从文件中读取目标 url,但它似乎仍然有点压倒我。

基本上相当于我在这里学习使用 Racket 所做的事情: Sending HTTP POST in Racket

有人能给我一个小的或最基本的例子吗?

我尝试阅读https://stackoverflow.com/a/13465653/5083453

【问题讨论】:

    标签: http haskell post functional-programming network-programming


    【解决方案1】:

    当然!这里要注意的奇怪的 Haskell 事情是 Haskell 的记录系统。当您使用 URL 字符串调用 parseUrl 时,http-conduit 会返回一个 Request 记录并填写一些默认值,但库希望您填写其余部分。

    例如,parseUrl 始终返回一个Request,并将 HTTP 方法设置为 GET。我们可以使用记录更新语法来覆盖该值——在花括号中附加新的键和值。

    {-# LANGUAGE OverloadedStrings #-}
    
    module Lib where
    
    import Data.Aeson
    import Network.HTTP.Client
    
    buildRequest :: String -> RequestBody -> IO Request
    buildRequest url body = do
      nakedRequest <- parseRequest url
      return (nakedRequest { method = "POST", requestBody = body })
    
    send :: RequestBody -> IO ()
    send s = do
      manager <- newManager defaultManagerSettings
      request <- buildRequest "http://httpbin.org/post" s
      response <- httpLbs request manager
      let Just obj = decode (responseBody response)
      print (obj :: Object)
    

    如果你在 GHCi 中运行它,你应该能够发送 POST 到 httpbin:

    λ> :set -XOverloadedStrings
    λ> send "hello there"
    fromList [("origin",String "<snip>")
             ,("args",Object (fromList []))
             ,("json",Null)
             ,("data",String "hello there")
             ,("url",String "http://httpbin.org/post")
             ,("headers",Object (fromList [("Accept-Encoding",String "gzip")
             ,("Host",String "httpbin.org")
             ,("Content-Length",String "11")]))
             ,("files",Object (fromList []))
             ,("form",Object (fromList []))]
    

    您还需要 OverloadedStrings 扩展。没有它,会发生两件事:

    • nakedRequest { method = "POST" } 不会进行类型检查,因为库需要来自 bytestring 库的(严格)ByteString。默认情况下,"POST" 和所有字符串文字的类型为 String 又名 [Char]。虽然有一个名为pack 的函数接受String 并返回ByteString,但打开重载字符串要简单得多。编译器会自动代表您调用pack。不止于此;有关详细信息,请参阅Oliver's blog post

    • 另一个不会进行类型检查的表达式是send "hello there"send 需要 RequestBody。虽然在某处还有一个函数类型为 String -&gt; RequestBody,但打开重载字符串并让编译器为您调用它要容易得多。

    【讨论】:

    • 非常感谢,现在这更有意义了。刚刚收到另一个问题:为什么需要使用重载字符串,或者换一种方式问:它们是做什么的?
    • 再次感谢您,这很有帮助,我有最后一个问题:我修改了您的示例,因此它将应该发布到的 url 作为字符串 send :: RequestBody -&gt; String -&gt; IO () 并尝试编写另一个函数它从文件中获取随机文本并发送它。我在其中得到了q &lt;- rndPick $ lines qs 行,然后在最后一行得到send q ur,这给了我错误Couldn't match type [Char]' 和RequestBody'。我假设在这种情况下我应该将我的 String 打包到 RequestBody 中,还是我错了?
    • 是的。在这种情况下,您需要将字符串打包成一个字节串,然后用these RequestBody constructors 之一包装该字节串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    相关资源
    最近更新 更多