I'm writing a webhook endpoint (receiving end) and don't really have control over the incoming Accept header in the request. Here's what it is:
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
I've tried Post '[JSON, HTML, PlainText] Text but it results in a 406 status code.
IIUC, Servant is unable to parse this as a valid Accept header due to the * (which should probably be */*) and the q=.2 (which should probably be q=0.2
How do I deal with this? The realistic situation is that I don't care about the Accept header, and the webhook sender doesn't really care about the response body (only the response code matters)
I found Network.HTTP.Media.Accept.Accept which has parseAccept :: ByteString -> Maybe a, which I tried using like this...
data IrrelevantAcceptHeader = IrrelevantAcceptHeader deriving (Show)
instance Network.HTTP.Media.Accept.Accept IrrelevantAcceptHeader where
parseAccept _ = Just IrrelevantAcceptHeader
matches _ _ = True
moreSpecificThan _ _ = False
hasExtensionParameters _ = True
instance Servant.Accept IrrelevantAcceptHeader where
contentType _ = fromString "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
instance MimeRender IrrelevantAcceptHeader Text where
mimeRender _ txt = toS txt
-- and here's how it's used:
data Routes route = Routes
{ rWebhook
:: route
:- "webhook"
:> Header' '[Required, Strict] "X-Api-Secret" Text
:> ReqBody '[JSON] Aeson.Value
:> Post '[IrrelevantAcceptHeader] Text
} deriving (Generic)
...but all this jugglery doesn't really work!
PS: This might be related to Haskell Servant (client): UnsupportedContentType error due to weird Accept header
You could consider writing a
Middlewareto fix up the brokenAcceptheader before it's passed toservant. This would affect all routes, but that's probably what you want anyway.It would look something like:
and when you run your Servant server, just wrap it in the middleware:
If you want to check in your Middleware whether or not a header fix is necessary, note that Servant uses
matchAcceptfromNetwork.HTTP.Mediain thehttp-mediapackage which in turn usesparseQualityto do the matching. You can check in the middleware ifparseQualitysucceeds or fails:As above, it appears to be the invalid quality numbers specifically that are causing problems.
This seems to be a known issue that, unfortunately, the developers are refusing to fix. Fortunately,
http-mediais open source with a permissive license, so you are free to patch it yourself for your own use or for redistribution.