问题:我正在尝试将一些JSON发布到仅接受Base64编码的HTTP端点。
代码示例:以下是无需 Base64编码即可成功发布的代码示例:
{-# LANGUAGE OverloadedStrings #-}
module Lib where
import Data.Aeson (encode, object, (.=))
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.HTTP.Client
import Network.HTTP.Client.TLS
import Network.HTTP.Types.Status (statusCode)
import qualified Data.ByteString.Base64 as B64
postJSON :: IO ()
postJSON = do
manager <- newManager tlsManagerSettings
-- Nested JSON object to POST:
let requestObject = object
[ "event" .= ("App launched." :: String)
, "properties" .= object [ "distinct_id" .= ("user" :: String)
, "token" .= ("f793bae9548d8e123cef251fd81df487" :: String)
]
]
initialRequest <- parseRequest "http://api.mixpanel.com/track"
let request = initialRequest
{ method = "POST"
, requestBody = RequestBodyLBS $ encode requestObject
, requestHeaders =
[ ("Content-Type", "application/json; charset=utf-8")
]
}
response <- httpLbs request manager
putStrLn $ "The status code was: "
++ show (statusCode $ responseStatus response)
L8.putStrLn $ responseBody response
尝试:为了将JSON发送为Base64编码,我尝试将requestBody = RequestBodyLBS $ encode requestObject
替换为requestBody = RequestBodyLBS $ Data.Bytestring.Base64.encode (encode requestObject)
,但是我收到了类型错误。那么如何将JSON编码为这个HTTP POST的Base64?
答案 0 :(得分:3)
B64.encode
here是一个从严格ByteString
到严格ByteString
的函数(您需要将鼠标悬停在黑线鳕的类型名称上,以查看此内容你只是在浏览),而Aeson.encode
返回一个懒惰的字节串(来自Data.ByteString.Lazy
模块)。这些是两种不同的类型,尽管它们具有相同的名称。
您可能需要执行以下操作:
...
requestBody = RequestBodyLBS $ L8.fromStrict $ Data.Bytestring.Base64.encode (L8.toStrict $ encode requestObject)
答案 1 :(得分:2)
我有两件事要添加到jberryman的答案中。
首先,如果(现在看来)你将把它放在一个查询字符串中,你需要确保你不只是使用base64编码的字节串,而是使用base64 url -encoded bytestring。因此,请勿使用Data.Bytestring.Base64
(与jberryman相关联),而应使用Data.Bytestring.Base64.URL
(here)。
其次,虽然他在Base64编码部分指出了正确的方向,但似乎你仍然在设置查询字符串。为此,您应该查看您已使用的setQueryString
库中的http-client
函数(链接here)。
该功能有签名:
setQueryString :: [(ByteString, Maybe ByteString)] -> Request -> Request
所以如果你是base64编码的bytestring就像这样构建
let urlEncodedBytestring = Data.Bytestring.Base64.URL.encode . L8.toStrict $ encode requestObject
如果您正在尝试在请求的查询字符串中设置data
键,那么您可能需要:
let requestWithQueryStringSet = setQueryString [("data", (Just urlEncodedBytestring))] request