【问题标题】:Haskell Servant (Client) - GET Request with headersHaskell Servant (Client) - 带有标头的 GET 请求
【发布时间】:2019-07-11 09:47:01
【问题描述】:

我正在尝试用 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 ""  

这就是我使用 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 请求中却没有。

我怀疑我的标题有问题,因为当我删除

'Accept: application/vnd.twitchtv.v5+json'

从 curl 请求中,我得到了完全相同的响应。

【问题讨论】:

  • 我已经多次使用servant-client 并且它有效,但我看不出您的查询有什么问题......对我来说看起来完全没问题,应该可以。如果您在这里没有得到答案,我建议您在 haskell-servant 存储库中创建一个问题并在那里提问。
  • Wireshark 显示什么?

标签: haskell servant


【解决方案1】:

是的,servant-client 对 Accept 和 Content-Type 标头进行了特殊处理——如果您尝试使用 :&gt; Header ... 机制包含它们,它们会在函数 requestToClientRequest 中从请求中删除Servant.Client.Internal.HttpClient.

我认为强制使用Accept 标头的最简单方法是向您的Manager 添加请求修改功能。这绝对是一个丑陋的黑客,但它似乎工作。 (我没有要测试的 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) }

【讨论】:

  • 行得通!从 Twitch API 获得预期的响应。
猜你喜欢
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
  • 2016-11-12
  • 2015-02-22
  • 2015-02-24
  • 2013-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多