Open diegotori opened 3 days ago
Summary: The Uri
class does not properly encode or double-encodes non-URL safe base64 path segments when creating a new Uri
instance or replacing an existing one. This results in incorrect URIs with unencoded or double-encoded path segments.
The =
character is a valid pchar, it's a sub-delimiter, so it doesn't need to be escaped.
That's why the replace
function doesn't escape it.
The pathSegments
argument is assumed to be unescaped source path segments (not pre-escaped URI path segments), so the %
is (double) escaped.
The Uri.encodeComponent
is used for query elements, like the name
and value
of ?name=value
, so it escapes =
characters, It doesn't know that the text will be used as a path segment where =
would be OK.
So, all in all, working as intended.
@lrhn I think it might make sense to point out this caveat in the existing documentation. Otherwise, other devs might get tripped up going forward.
True, let's make it a documentation issue.
When attempting to create a
Uri
with a base64 encoded path segment value that is NOT URL safe (i.e containing illegal characters), it does not encode it (or double-encodes it when encoding it prior to creating the instance), when either creating a URI from scratch, or when replacing an existing one.In other words, when encoding the base64 value using
Uri.encodeComponent
and creating theUri
usingUri.parse
, it properly converts the unsafe==
into properly encoded%3D%3D
characters.However, when creating the
Uri
either from its constructor, or when callingreplace
on an existing one, when placing an unencoded base64 value as a path segment, it returns==
when callingtoString
on the resulting instance. Furthermore, when encoding the value usingUri.encodeComponent
and placing it as a path segment, it double-encodes the already encoded%3D%3D
value to%253D%253D
instead.Here is code that highlights this issue:
Also available as a DartPad.
Currently running the following Dart version on macOS 14.5: