1

无论我输入什么值作为请求的“Content-Type”,我发出的传出请求似乎都会用“application/x-www-form-urlencoded”替换它。我试图命中的应用程序需要“application/json”。基本上,我的代码如下。

{-# LANGUAGE OverloadedStrings #-}

import Network.Wreq

...

submissionResources = ["https://widgets.example.com/v2/widgets/request"]

sendWidgetToEndpoint submissionResources workingToken key widgetArray = do
    let opts            = defaults & header "Content-Type"  .~ ["application/json"]
                                   & header "apikey"        .~ [key]
                                   & header "Authorization" .~ [workingToken]
        endPointURL     = head submissionResources 
        widgetId        = widgetArray !! 0
        numberOfWidgets = widgetArray !! 1
        widgetText      = widgetArray !! 2
    submissionResult <- postWith opts endPointURL [ "widgetId"     := widgetId
                                                  , "numWidgets"   := numberOfWidgets
                                                  , "widgetText"   := widgetText
                                                  ]
    return submissionResult

我的问题是我不断Status {statusCode = 415, statusMessage = "Unsupported Media Type"}从这个端点返回,我相信这是因为我发送的请求似乎覆盖了我的标头中的“Content-Type”。我曾尝试使用“application/json”和“text/plain”,但我得到的响应总是向我表明,我发送的所有标头看起来都符合预期,除了 Content-Type 总是变成“application/x-www” -form-urlencoded”。

如何确保 wreq 在我的请求标头中保留“Content-Type: application/json”?

编辑:我正在通过 API 服务器在回复我时告诉我的内容来确定我的原始请求中的标头。

4

1 回答 1

3

postWith您的代码段中最后一个参数的类型是[FormParam],并且该类型是强制 Content-Type 被 urlencoded 的原因。

要发送 JSON,请发送类型ValueEncoding(from Data.Aeson) 的内容。

import Data.Aeson (pairs, (.=))

  ...
  -- also remove the "Content-Type" field from opts
  submissionResult <- postWith opts endpointURL $ pairs
    ( "widgetId" .= widgetId <>
      "numWidgets" .= numberOfWidgets <>
      "widgetText" .= widgetText )
  ...

Content-Type 由您通过实例传递给的有效负载postWith设置Postable。如果您想使用另一个 Content-Type 标头,请使用Postable您设置适当 Content-Type 的实例定义您自己的类型。您也可以选择不在Postable实例中设置任何 Content-Type,因此您可以通过选项进行设置。

于 2020-03-30T19:58:17.050 回答