Skip to content

Double encoding of percent signs (servant-client) #1418

Closed
@GambolingPangolin

Description

@GambolingPangolin

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions