简体   繁体   中英

Is postWith switching my request's Content-Type?

No matter what value I enter as my request's "Content-Type", the outgoing request I send out seems to replace it with "application/x-www-form-urlencoded". The application I'm trying to hit expects "application/json". My code, basically, is below.

{-# 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

My problem is that I keep getting back Status {statusCode = 415, statusMessage = "Unsupported Media Type"} from this endpoint, and I'm confident this is because the request I'm sending appears to be overriding "Content-Type" in my header. I have tried using "application/json" and "text/plain" but the response I get back always indicates to me that all the headers I sent over look as expected except for Content-Type which invariably has become "application/x-www-form-urlencoded".

How can I ensure wreq keeps 'Content-Type: application/json' in my requests header?

EDIT: I'm determining what headers were in my original request by what the API server tells me in its response back to me.

The type of the last argument to postWith in your snippet is [FormParam] , and that type is what forces the Content-Type to be urlencoded.

To send JSON, send something of type Value or Encoding (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 )
  ...

The Content-Type is set by the payload you pass to postWith , via the Postable instance. If you want to use yet another Content-Type header, define your own type with a Postable instance where you set an appropriate Content-Type. You can also choose to not set any Content-Type in the Postable instance, so you can set it via the options instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM