Haskell 仆人(客户端)- headers 的 GET 请求
Haskell Servant (Client) - GET Request with headers
我正在尝试用 Haskell Servant
复制这个 curl 请求
curl -v -H 'Accept: application/vnd.twitchtv.v5+json' \
-H 'Client-ID: someapikey' \
-X GET 'https://api.twitch.tv/kraken/clips/top?game=Overwatch&period=week&trending=false&limit=3'
使用 Twitch API。文档 here
这是我目前得到的
type Game = Text
type Cursor = Text
type Language = Text
type Limit = Int
type Period = Text
type Trending = Bool
type Application = Text
type ClientID = Text
type SearchClips = "kraken"
:> "clips"
:> "top"
:> QueryParam "game" Game
:> QueryParam "cursor" Cursor
:> QueryParam "language" Language
:> QueryParam "limit" Limit
:> QueryParam "period" Period
:> QueryParam "trending" Trending
:> Header "Accept" Application
:> Header "Client-ID" ClientID
:> Get '[JSON] Search
searchClipAPI :: Proxy SearchClips
searchClipAPI = Proxy
search
:: Maybe Game
-> Maybe Cursor
-> Maybe Language
-> Maybe Limit
-> Maybe Period
-> Maybe Trending
-> Maybe Application
-> Maybe ClientID
-> ClientM Search
search = client searchClipAPI
baseURL :: BaseUrl
baseURL = BaseUrl Https "api.twitch.tv" 443 ""
这就是我 'run' 和 http-tls
的方式
runGameClipsSearchClient :: Maybe Text -> IO ()
runGameClipsSearchClient game = do
mn <- NT.newTlsManager
let args = search
game
(Just "")
(Just "en")
(Just 50)
(Just "day")
(Just False)
(Just "application/vnd.twitchtv.v5+json")
(Just "someapikey")
envClient = mkClientEnv mn baseURL
pPrint =<< runClientM args envClient
但我一定是做错了什么,因为 haskell 代码出现“404:未找到”错误,而 curl 请求却没有。
我怀疑我的 headers 有问题,因为当我删除
'Accept: application/vnd.twitchtv.v5+json'
从 curl 请求中,我得到了完全相同的响应。
是的,servant-client
对 Accept
和 Content-Type
header 有特殊处理——如果您尝试使用 :> Header ...
机制包含它们,它们在 Servant.Client.Internal.HttpClient
.
中的函数 requestToClientRequest
中被从请求中删除
我认为强制 Accept
header 的最简单方法是向 Manager
添加请求处理功能。这绝对是一个丑陋的 hack,但它似乎有效。 (我没有要测试的 Twitch 客户端 ID,但通过此修复,我得到了 400 而不是 404 错误,我认为这是进步。)
mn <- NT.newTlsManagerWith (NT.tlsManagerSettings { managerModifyRequest = fixAccept })
...
where fixAccept req
= return $ req { requestHeaders = ("Accept", "application/vnd.twitchtv.v5+json") :
filter (("Accept" /=) . fst) (requestHeaders req) }
我正在尝试用 Haskell Servant
复制这个 curl 请求curl -v -H 'Accept: application/vnd.twitchtv.v5+json' \
-H 'Client-ID: someapikey' \
-X GET 'https://api.twitch.tv/kraken/clips/top?game=Overwatch&period=week&trending=false&limit=3'
使用 Twitch API。文档 here
这是我目前得到的
type Game = Text
type Cursor = Text
type Language = Text
type Limit = Int
type Period = Text
type Trending = Bool
type Application = Text
type ClientID = Text
type SearchClips = "kraken"
:> "clips"
:> "top"
:> QueryParam "game" Game
:> QueryParam "cursor" Cursor
:> QueryParam "language" Language
:> QueryParam "limit" Limit
:> QueryParam "period" Period
:> QueryParam "trending" Trending
:> Header "Accept" Application
:> Header "Client-ID" ClientID
:> Get '[JSON] Search
searchClipAPI :: Proxy SearchClips
searchClipAPI = Proxy
search
:: Maybe Game
-> Maybe Cursor
-> Maybe Language
-> Maybe Limit
-> Maybe Period
-> Maybe Trending
-> Maybe Application
-> Maybe ClientID
-> ClientM Search
search = client searchClipAPI
baseURL :: BaseUrl
baseURL = BaseUrl Https "api.twitch.tv" 443 ""
这就是我 'run' 和 http-tls
的方式runGameClipsSearchClient :: Maybe Text -> IO ()
runGameClipsSearchClient game = do
mn <- NT.newTlsManager
let args = search
game
(Just "")
(Just "en")
(Just 50)
(Just "day")
(Just False)
(Just "application/vnd.twitchtv.v5+json")
(Just "someapikey")
envClient = mkClientEnv mn baseURL
pPrint =<< runClientM args envClient
但我一定是做错了什么,因为 haskell 代码出现“404:未找到”错误,而 curl 请求却没有。
我怀疑我的 headers 有问题,因为当我删除
'Accept: application/vnd.twitchtv.v5+json'
从 curl 请求中,我得到了完全相同的响应。
是的,servant-client
对 Accept
和 Content-Type
header 有特殊处理——如果您尝试使用 :> Header ...
机制包含它们,它们在 Servant.Client.Internal.HttpClient
.
requestToClientRequest
中被从请求中删除
我认为强制 Accept
header 的最简单方法是向 Manager
添加请求处理功能。这绝对是一个丑陋的 hack,但它似乎有效。 (我没有要测试的 Twitch 客户端 ID,但通过此修复,我得到了 400 而不是 404 错误,我认为这是进步。)
mn <- NT.newTlsManagerWith (NT.tlsManagerSettings { managerModifyRequest = fixAccept })
...
where fixAccept req
= return $ req { requestHeaders = ("Accept", "application/vnd.twitchtv.v5+json") :
filter (("Accept" /=) . fst) (requestHeaders req) }