std.http.Client does not handle all valid Location header values.
Currently std.http.Client assumes that the Location header is a well formed URI. However that is not actually how it should be parsed according to the spec.
https://www.rfc-editor.org/rfc/rfc9110.html#section-10.2.2
Location is a URI-reference, which can be a invalid URI (in the form of a file path relative to the current location). Additionally, the request must inherit the fragment of the current location if the Location header provides none
From the ABNF:
URI-reference = URI / relative-ref
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
relative-ref = relative-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
relative-part = "//" authority path-abempty
/ path-absolute
/ path-noscheme
/ path-empty
From this we can see that URI and relative-ref differ only by the lack of scheme:, which may raise an issue with the URI parser (maybe we need to add a way to allow parsing a URI without a scheme?)
These are quite rare in practice, most servers give you a well formed URI, but some don't and this needs to be resolved at some point.
Hi, may I give a try ?
My plan is to make Uri.parse a generic function over a comptime strict bool. If strict it returns a Uri, otherwise it returns a tagged union Uri | Reference.
Uri interface will not be impacted, as I don't want to leak HTTP-specific stuff in Uri. (I will probably have to create a private uri/ dir, but it's transparent for the user).
In std.http.client.Response.readAdvanced, I resolve the union as a Uri, using the scheme of the original request.
Sounds good ?
This was mostly fixed in #14762, will need some verification that it handles everything correctly.
Closing for now as no major problems have been reported. Individual cases where this is incorrect should be filed as new issues.