Description
First of all, this is a wonderful project and very useful. Now, down to business.
When using defaults, servant-client
code can double-encode percent signs in query parameters. Consider this (incomplete) example:
newtype UrlEncoded = UrlEncoded { unUrlEncoded :: ByteString }
instance ToHttpApiData UrlEncoded where
toQueryParam = decodeUtf8 . urlEncode True . unUrlEncoded
type ExampleEndpoint = QueryParam "value" UrlEncoded :> GetNoContent
exampleEndpoint :: UrlEncoded -> ClientM ()
exampleEndpoint = client $ Proxy @ExampleEndpoint
problemCall :: ClientM ()
problemCall = exampleEndpoint $ UrlEncoded "\x01"
Running problemCall
creates a request with query string ?value=%2501
. I believe the reason is that the HasClient
instance of QueryParam
uses toQueryParam
when adding the parameter to the (servant) Request
it builds up, then defaultMakeClientRequest
calls renderQuery
which re-encodes the string while marshalling a (http-client) Request
.
It is my understanding that ToHttpApiData (toQueryParam)
is meant to produce escaped output. Therefore, it seems that defaultMakeClientRequest
should use a custom version of renderQuery
which does not escape values.