这是我的尝试试图连接到TDAmeritrade的api
使用haskell中的Network。HTTP。Req库接收json响应。
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Lib
import Wuss
import Control.Concurrent
import Control.Monad
import Data.Text
import Network.WebSockets
import Network.Connection
import Network.WebSockets.Stream
import Data.Text.Lazy
import Data.ByteString
import Lens.Micro.GHC.Internal
import Network.Curl
import Data.ByteString.Lazy.UTF8
import Network.HTTP.Req
import Control.Monad
import Control.Monad.IO.Class
import Data.Aeson
import Data.Maybe
import Data.Monoid
import GHC.Generics
import Network.HTTP.Req
import Data.ByteString.Char8
tok = Data.ByteString.Char8.pack "accesstoken"
main :: IO ()
main = runReq defaultHttpConfig $ do
v <- req GET (https "api.tdameritrade.com" /: "v1" /: "userprincipals?fields=streamerConnectionInfo") (NoReqBody) jsonResponse (oAuth2Bearer tok)
liftIO $ Data.ByteString.Char8.putStrLn (responseBody v)
如果操作正确,响应应该只给出一个错误,即认证令牌不正确,因为我在这里故意没有提供有效的令牌。“accesstoken”
如果我使用bsResponse而不是jsonResponse,它的类型检查,但它不与jsonResponse类型检查。来自TDAmeritrade的响应将是JSON格式的。
错误如下:
No instance for (FromJSON Data.ByteString.Char8.ByteString)
arising from a use of ‘req’
这是如果我使用bsResponse的结果:
port = 443
secure = True
requestHeaders = [("Authorization","<REDACTED>")]
path = "/v1/userprincipals%3Ffields=streamerConnectionInfo"
queryString = ""
method = "GET"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
(StatusCodeException (Response {responseStatus = Status {statusCode = 400, statusMessage = "Bad Request"}, responseVersion = HTTP/1.1, responseHeaders = [("Date","Wed, 08 Sep 2021 15:27:41 GMT"),("Content-Type","application/json"),("Content-Length","78"),("Connection","keep-alive"),("Host","api.tdameritrade.com"),("X-Forwarded-Port","9002"),("X-Forwarded-Proto","http"),("Accept-Encoding","gzip"),("Authorization","Bearer accesstoken"),("NS-Proxy-Client-IP","82.46.185.98"),("Access-Control-Allow-Origin",""),("Access-Control-Allow-Headers","origin, x-requested-with, accept, authorization, content-type, correlationid, apikey, application-name"),("Access-Control-Max-Age","3628800"),("Access-Control-Allow-Methods","GET, PUT, POST, DELETE, OPTIONS, HEAD, PATCH"),("X-Xss-Protection","1; mode=block"),("X-Content-Type-Options","nosniff"),("X-Frame-Options","SAMEORIGIN"),("Content-Security-Policy","frame-ancestors 'self'"),("Cache-Control","no-cache,no-store,must-revalidate"),("Strict-Transport-Security","max-age=31536000")], responseBody = (), responseCookieJar = CJ {expose = []}, responseClose' = ResponseClose}) "\n {\n \"error\":\"The endpoint doesnt exist.\"\n \t\t}\n "))
为了参考,这个curl命令在终端中会产生正确的响应:
curl -X GET --header "Authorization: Bearer authorizationtoken" "https://api.tdameritrade.com/v1/userprincipals?fields=streamerConnectionInfo"
我完全迷路了。请帮助
###要修复你的即时错误,你必须使用(=:)
function construct the request parameter instead of m函数构造请求参数,而不是手动编写?fields=streamerConnectionInfo
part. And you also need to disable error status code checking. This is wo部分。您还需要禁用错误状态代码检查。这是复制您的curl
command:
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Char8
import Network.HTTP.Req
import Control.Monad.IO.Class
import Data.Text
tok = Data.ByteString.Char8.pack "accesstoken"
main :: IO ()
main = runReq defaultHttpConfig { httpConfigCheckResponse = \_ _ _ -> Nothing } $ do
v <- req GET (https "api.tdameritrade.com" /: "v1" /: "userprincipals") (NoReqBody) bsResponse ("fields" =: ("streamerConnectionInfo" :: Text) <> oAuth2Bearer tok)
liftIO $ Data.ByteString.Char8.putStrLn (responseBody v)
另一个问题是访问JSON正文中的字段。我建议从阅读Aeson的文档开始,Aeson是Haskell JSON的主包。如果你使用jsonResponse请求类型,那么它会自动将响应转换为任何带有FromJSON实例的类型。
也许这个关于在Haskell中使用JSON的stackoverflow答案也可以帮助你。