[英]Encoding JSON as Base64 Before HTTP POSTing It (in Haskell)
Problem: I am attempting to POST some JSON to an HTTP endpoint that only accepts Base64 encoding . 问题:我正在尝试将一些JSON发布到仅接受Base64编码的HTTP端点。
Code Sample: Here is a code sample which successfully posts without Base64 encoding: 代码示例:以下是无需使用 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
Attempt: In order to send the JSON as Base64 encoded, I tried replacing requestBody = RequestBodyLBS $ encode requestObject
with requestBody = RequestBodyLBS $ Data.Bytestring.Base64.encode (encode requestObject)
, but I get a type error. 尝试:为了以Base64编码形式发送JSON,我尝试用
requestBody = RequestBodyLBS $ Data.Bytestring.Base64.encode (encode requestObject)
替换requestBody = RequestBodyLBS $ encode requestObject
,但是出现类型错误。 So how do I encode the JSON as Base64 for this HTTP POST? 那么,如何为此HTTP POST将JSON编码为Base64?
B64.encode
here is a function from strict ByteString
to strict ByteString
(you'll need to hover over the type name in the haddocks to see this if you're just browsing), while Aeson.encode
returns a lazy bytestring (from the Data.ByteString.Lazy
module). B64.encode
这里是从严格的功能ByteString
,以严格ByteString
(你需要将鼠标悬停在类型名称的黑线鳕,看看这个,如果你只是浏览),而Aeson.encode
返回一个懒惰的字节串(从Data.ByteString.Lazy
模块)。 These are two distinct types although they have the same name. 尽管它们具有相同的名称,但它们是两种不同的类型。
You probably have to do something like: 您可能需要执行以下操作:
...
requestBody = RequestBodyLBS $ L8.fromStrict $ Data.Bytestring.Base64.encode (L8.toStrict $ encode requestObject)
I have two things to add to jberryman's answer. 我要在jberryman的答案中添加两件事。
First, if (as it now appears) you're going to be putting this in a query string, you need to make sure you don't just use a base64 encoded bytestring, but instead use a base64 url-encoded bytestring. 首先,如果(要显示出来)将其放入查询字符串中,则需要确保您不仅使用base64编码的字节串,还使用base64 url编码的字节串。 So don't use
Data.Bytestring.Base64
(as jberryman linked to), but rather Data.Bytestring.Base64.URL
( here ). 因此,请勿使用
Data.Bytestring.Base64
(与jberryman链接),而应使用Data.Bytestring.Base64.URL
( 此处 )。
Second, while he pointed you in the right direction on the Base64 encoding part, it seems you're still hung up on setting the querystring. 其次,尽管他在Base64编码部分为您指明了正确的方向,但似乎您仍然挂在设置查询字符串上。 For that, you should check out the
setQueryString
function in the http-client
library you're already using (link here ). 为此,您应该在已经使用的
http-client
库中setQueryString
函数( 在此处链接)。
That function has the signature: 该函数具有签名:
setQueryString :: [(ByteString, Maybe ByteString)] -> Request -> Request
So if you're base64 encoded bytestring is built like this 因此,如果您是base64编码的字节串,将像这样构建
let urlEncodedBytestring = Data.Bytestring.Base64.URL.encode . L8.toStrict $ encode requestObject
and if you're attemtping to set the data
key in the querystring of your request, then you'll probably want: 并且如果您打算在请求的查询字符串中设置
data
键,那么您可能需要:
let requestWithQueryStringSet = setQueryString [("data", (Just urlEncodedBytestring))] request
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.