Equal signs in query parameter values are not parsed correctly
lydell opened this issue · 0 comments
This is a valid URL:
It has a query parameter called q
with the value a=b
.
ctx.request.query
does not contain the q
parameter at all though – it’s dropped. Because of the equals sign in the value.
A workaround is to escape that equals sign:
Here’s how System.Web.HttpUtility.ParseQueryString
, Python and Node.js/browsers parse it (they all handle unescaped equal signs in query paramter values):
❯ dotnet fsi
Microsoft (R) F# Interactive version 12.4.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> System.Web.HttpUtility.ParseQueryString("?q=a=b").Get("q");;
val it: string = "a=b"
❯ python3
Python 3.11.2 (main, Feb 16 2023, 02:55:59) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib.parse
>>> urllib.parse.parse_qs("q=a=b")["q"]
['a=b']
❯ node
Welcome to Node.js v16.17.0.
Type ".help" for more information.
> new URLSearchParams("?q=a=b").get("q")
'a=b'
I believe this is the relevant section in the WHATWG URL spec:
https://url.spec.whatwg.org/#urlencoded-parsing
If bytes contains a 0x3D (=), then let name be the bytes from the start of bytes up to but excluding its first 0x3D (=), and let value be the bytes, if any, after the first 0x3D (=) up to the end of bytes. If 0x3D (=) is the first byte, then name will be the empty byte sequence. If it is the last, then value will be the empty byte sequence.
This code splits on =
but only uses the value if the splitted list has length 2. It needs to either use the head as the key, and join the tail back up with =
, or split just on the first equals sign:
suave/src/Suave/Utils/Parsing.fs
Lines 18 to 27 in 8efe4b3