當然!哈斯克爾奇怪的事情是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
的函數,但打開重載字符串並讓編譯器爲您調用它會容易得多。
來源
2015-11-29 15:56:56
hao
非常感謝你,這使得現在更有意義。剛剛又得到了另外一個問題:爲什麼需要使用Overloaded Strings或者以不同的方式提問:他們做了什麼? –
@learningProgged添加了關於它的後記! – hao
再次感謝你,這有幫助,我得到了最後一個問題:我修改了你的例子,所以它把它應該發佈到的url作爲一個String'send :: RequestBody - > String - > IO()'並嘗試編寫另一個從文件中獲取隨機文本併發送它的函數。我在裏面找到了'q < - rndPick $ lines qs'行,然後在最後一行發送'q ur',這給了我錯誤'無法與'RequestBody'匹配類型'[Char]'。在這種情況下,我認爲我應該將我的字符串打包爲一個RequestBody,或者我錯了嗎? –