You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The query parameter URL-encoding has undocumented behavior. I was trying to write some HasServer and HasClient instances working with Query and oh boy, what it took me a while to get out of that rabbit hole.
However the servant-client introduced a risky approach to client parameter encoding when #1432 was merged (and doesn't even seems necessary). Now only query keys are implicitly encoded. QueryParam' and QueryParams seem to be aware of this (after some bugfixes), and explicitly encode the value using encodeQueryParam (QueryParam' and QueryParams instances).
However since then, few more query handling types were introduced and they seem to be unaware of the fact. Namely QueryString (the main issue here is undocumented behavior - both server and client-vise, developers won't know what to expect while using it) and DeepQuery (no URL-encoding is performed here either).
There have been few issues/PRs related to URL-encoding reported in the past:
But the source of the issue is still there. There's nothing saying whether the requestQueryString :: Query in the client's `Request' should or should not be URL-encoded (be it documentation or the types).
Proposal
I think the surefire solution would be to switch to PartialEscapeQuery for servant-client, which forces selection of URL-encoding on the type level and encoding it using renderQueryPartialEscape.
Such change will introduce an API incompatibility with older versions, but that's actually for the best as it will force everyone to review their implementations. Also the migration should be quite easy, wrapping any existing values into list of QE's or QN's (EscapeItem's constructors) and replacing Nothing with empty list. Introducting some smart constructors can make it even easier.
And for servant-server documenting that QueryString returns URL-decoded keys and values would also be a good idea. Not sure whether anything more can be done. Wrapping value in something like newtype UrlDecodedQueryValue = QD ByteString (names are just example, not a suggestion) to give the info on the type level seems to be excessive. Maybe a documented type alias like type DecodedQuery = Query would not hurt.
Any reservations/feedback before I start producing a PR?
The text was updated successfully, but these errors were encountered:
The query parameter URL-encoding has undocumented behavior. I was trying to write some
HasServer
andHasClient
instances working withQuery
and oh boy, what it took me a while to get out of that rabbit hole.servant-server
is based onwai
which uses parseQuery (https://github.com/yesodweb/wai/blob/master/warp/Network/Wai/Handler/Warp/Request.hs#L108). This will always properly decode both query key and value.However the
servant-client
introduced a risky approach to client parameter encoding when #1432 was merged (and doesn't even seems necessary). Now only query keys are implicitly encoded.QueryParam'
andQueryParams
seem to be aware of this (after some bugfixes), and explicitly encode the value usingencodeQueryParam
(QueryParam' and QueryParams instances).However since then, few more query handling types were introduced and they seem to be unaware of the fact. Namely QueryString (the main issue here is undocumented behavior - both server and client-vise, developers won't know what to expect while using it) and DeepQuery (no URL-encoding is performed here either).
There have been few issues/PRs related to URL-encoding reported in the past:
Now there's a proposed solution based on fizruk/http-api-data#120 (toEncodedQueryParam) that is attempting somewhat fixing the symptoms:
But the source of the issue is still there. There's nothing saying whether the
requestQueryString :: Query
in the client's `Request' should or should not be URL-encoded (be it documentation or the types).Proposal
I think the surefire solution would be to switch to PartialEscapeQuery for
servant-client
, which forces selection of URL-encoding on the type level and encoding it usingrenderQueryPartialEscape
.Such change will introduce an API incompatibility with older versions, but that's actually for the best as it will force everyone to review their implementations. Also the migration should be quite easy, wrapping any existing values into list of
QE
's orQN
's (EscapeItem's constructors) and replacingNothing
with empty list. Introducting some smart constructors can make it even easier.And for
servant-server
documenting thatQueryString
returns URL-decoded keys and values would also be a good idea. Not sure whether anything more can be done. Wrapping value in something likenewtype UrlDecodedQueryValue = QD ByteString
(names are just example, not a suggestion) to give the info on the type level seems to be excessive. Maybe a documented type alias liketype DecodedQuery = Query
would not hurt.Any reservations/feedback before I start producing a PR?
The text was updated successfully, but these errors were encountered: