Suppose I have this function performing a get request:
import Network.HTTP.Conduit
import qualified Data.ByteString.Char8 as C8
get :: String -> [(C8.ByteString, C8.ByteString)] -> IO (Response LC8.ByteString)
get url par = do
request <- parseUrl url
res <- withManager $ httpLbs $ createReq request
return res
where
createReq req =
req {
method = methodGet
, queryString = map (\(k, v) -> k ++ "&=" ++ v) par -- ????
}
I believe there must a simpler way to create a query string. My method both is not simple and wrong as it doesn't care about "?" and "&" (there must be "?" in the beggining and must not be "&" at the end). So how do I create a query string for a get request from [(C8.ByteString, C8.ByteString)]
? Moreover, (++) can't be used with ByteString. But I haven't found any example which is surprising.
Use functions from Network.HTTP.Types.URI present in http-types
package. Infact, http-types
is one of the dependency package for http-conduit
.
λ> import Network.HTTP.Types.URI
λ> import Data.ByteString
λ> :set -XOverloadedStrings
λ> let getData = [("key1", Just "value1"), ("key2", Just "value2")] :: [(ByteString, Maybe ByteString)]
λ> renderQuery True getData
"?key1=value1&key2=value2"
λ> renderQuery False getData
"key1=value1&key2=value2"
See how the Bool
value in renderQuery
controls prepending ?
to the request.
Update: Starting from http-client 0.3.6
, Michael Snoyman has added this functionality in setQueryString as indicated by him in the comments.