haskell-servant / servant

Main repository for the servant libraries — DSL for describing, serving, querying, mocking, documenting web applications and more!
https://docs.servant.dev/
1.8k stars 407 forks source link

Client flexibility between request's Accept and response's Content-Type? #292

Open tomtau opened 8 years ago

tomtau commented 8 years ago

What is the best way to wrap APIs where Content-Type in the response header does not exactly match Accept in the request header? For example, Travis API requires the request header to contain Accept: application/vnd.travis-ci.2+json, but returns Content-Type: application/json;charset=utf-8 in the response header.

jkarni commented 8 years ago

Ouch. They're versioning their API via content-types? From our part, we'd need to pass in a list to Servant.Common.Req.performRequestCT, and accept any of those. Seems like a good idea in any case. Then you could (I hope!) send multiple accept content-types, with vnd... as the first, and we'd handle any of the ones returned.

I don't think there's a way around it now, modulo intercepting the request/response.

cdepillabout commented 7 years ago

I think #614 and #615 should be able to be used to work around this.

hamishmack commented 7 years ago

github has the same issue with its early access api. They require Accept: application/vnd.github.machine-man-preview+json in the request, but return Content-Type: application/json; charset=utf-8 in the response.

hamishmack commented 7 years ago

As @cdepillabout suggested, I used #614 & #615 and was able to get github early access working with:

data EarlyAccessJSON

instance FromJSON t => MimeUnrender EarlyAccessJSON t where
    mimeUnrender _ = mimeUnrender (Proxy :: Proxy JSON)

instance Accept EarlyAccessJSON where
    contentTypes _ = "application" M.// "vnd.github.machine-man-preview+json"
                          NE.:| ["application" M.// "json"]
christian-marie commented 7 years ago

Eew. If anyone's wondering, it's technically kosher:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.7

      Note: HTTP/1.1 servers are allowed to return responses which are
      not acceptable according to the accept headers sent in the
      request. In some cases, this may even be preferable to sending a
      406 response. User agents are encouraged to inspect the headers of
      an incoming response to determine if it is acceptable.