1

我想要學習如何使用Haskell和http-conduit(以便它可以與https協同工作)通過HTTP/POST發送簡單字符串,讀取目標url從一個文件,但它似乎仍然有點壓倒性給我。使用http-conduit在Haskell中發送HTTP/POST的基本方法

基本上就是我學會了球拍在這裏做等價的: Sending HTTP POST in Racket

可能有人給我這樣的一個小或最基本的例子嗎?

我試過閱讀https://stackoverflow.com/a/13465653/5083453

回答

8

當然!哈斯克爾奇怪的事情是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 -> RequestBody的函數,但打開重載字符串並讓編譯器爲您調用它會容易得多。

+1

非常感謝你,這使得現在更有意義。剛剛又得到了另外一個問題:爲什麼需要使用Overloaded Strings或者以不同的方式提問:他們做了什麼? –

+1

@learningProgged添加了關於它的後記! – hao

+0

再次感謝你,這有幫助,我得到了最後一個問題:我修改了你的例子,所以它把它應該發佈到的url作爲一個String'send :: RequestBody - > String - > IO()'並嘗試編寫另一個從文件中獲取隨機文本併發送它的函數。我在裏面找到了'q < - rndPick $ lines qs'行,然後在最後一行發送'q ur',這給了我錯誤'無法與'RequestBody'匹配類型'[Char]'。在這種情況下,我認爲我應該將我的字符串打包爲一個RequestBody,或者我錯了嗎? –