-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: UriCreationOptions #59099
Comments
Tagging subscribers to this area: @maryamariyan Issue DetailsBackground and motivation
It does this based on the recommendations of the Uri RFC. Some services, however, rely on specific behavior that may be impossible to replicate using .NET's I propose adding a
API Proposalnamespace System
{
// New type
public readonly struct UriCreationOptions
{
public bool AllowImplicitFilePaths { get; init; }
public bool DangerousUseRawPathAndQuery { get; init; }
public UriKind UriKind { get; }
public UriCreationOptions(UriKind uriKind);
}
public partial class Uri
{
// Existing
public Uri(string uriString);
public Uri(string uriString, UriKind uriKind);
// New
public Uri(string uriString, UriCreationOptions creationOptions);
// Existing
public static bool TryCreate(string? uriString, UriKind uriKind, out Uri? result);
// New
public static bool TryCreate(string? uriString, UriCreationOptions creationOptions, out Uri? result);
}
} Alternative names for
Behavior of
API Usagestring uriString = "/foo";
Uri.TryCreate(uriString, new UriCreationOptions { AllowImplicitFilePaths = false }, out var uri); // False var options = new UriCreationOptions { DangerousUseRawPathAndQuery = true };
var uri = new Uri("http://foo/%41", options);
// Server receives /%41 instead of /A Alternative API
RisksSetting For example:
|
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivation
It does this based on the recommendations of the Uri RFC. Some services, however, rely on specific behavior that may be impossible to replicate using .NET's I propose adding a
API Proposalnamespace System
{
// New type
public readonly struct UriCreationOptions
{
public bool AllowImplicitFilePaths { get; init; }
public bool DangerousUseRawPathAndQuery { get; init; }
public UriKind UriKind { get; }
public UriCreationOptions(UriKind uriKind);
}
public partial class Uri
{
// Existing
public Uri(string uriString);
public Uri(string uriString, UriKind uriKind);
// New
public Uri(string uriString, UriCreationOptions creationOptions);
// Existing
public static bool TryCreate(string? uriString, UriKind uriKind, out Uri? result);
// New
public static bool TryCreate(string? uriString, UriCreationOptions creationOptions, out Uri? result);
}
} Alternative names for
Behavior of
API Usagestring uriString = "/foo";
Uri.TryCreate(uriString, new UriCreationOptions { AllowImplicitFilePaths = false }, out var uri); // False var options = new UriCreationOptions { DangerousUseRawPathAndQuery = true };
var uri = new Uri("http://foo/%41", options);
// Server receives /%41 instead of /A Alternative API
RisksSetting For example:
|
namespace System
{
public struct UriCreationOptions
{
public UriKind UriKind { readonly get; set; }
public bool AllowImplicitFilePaths { readonly get; set; }
public bool DangerousDisablePathAndQueryCanonicalization { readonly get; set; }
}
public partial class Uri
{
// Existing
// public Uri(string uriString);
// public Uri(string uriString, UriKind uriKind);
public Uri(string uriString, in UriCreationOptions creationOptions);
// Existing
// public static bool TryCreate(string? uriString, UriKind uriKind, out Uri? result);
public static bool TryCreate(string? uriString, in UriCreationOptions creationOptions, out Uri? result);
}
} |
Part of the API surface was added in 6.0 RC2 to address #52628 and #58057 customer reprots.
Added in 6.0 RC2 and 7.0 PRs: public struct UriCreationOptions
{
public bool DangerousDisablePathAndQueryCanonicalization { readonly get; set; }
}
public partial class Uri
{
// Existing
// public Uri(string uriString);
// public Uri(string uriString, UriKind uriKind);
public Uri(string uriString, in UriCreationOptions creationOptions);
// Existing
// public static bool TryCreate(string? uriString, UriKind uriKind, out Uri? result);
public static bool TryCreate(string? uriString, in UriCreationOptions creationOptions, out Uri? result);
} Remaining parts, not yet implemented: public struct UriCreationOptions
{
public UriKind UriKind { readonly get; set; }
public bool AllowImplicitFilePaths { readonly get; set; }
} |
There is one case in RFC 8089, which |
|
I read it as if we are adding a new mode/flag for canonical form to support formats which weren't possible to support before (due to Uri's compatibility concerns). If that's not the case, nvm. |
Note to self: most of the missing implementation work is done in MihaZupan@fef4435 (not updated after #59173). |
I might be totally wrong here, but I was not really able to find this (in my eyes) unexpected behavior related to UriKind.Absolute in combination with implicit filepaths (linux) in the docs (msdn). Maybe it would be a great idea to put some giant warning blocks in the docs describing the behavior. And then secondary prioritize the work to have stricter parsing as described above and preferrable deprecate the existing loose parsing (secure by default) |
Background and motivation
Uri
validates the input and (if needed) converts it into a normalized (canonical) representation.For example, it will:
%20
)%41
turns intoA
)/foo/./bar/../
turns into/foo/
)It does this based on the recommendations of the Uri RFC.
Some services, however, rely on specific behavior that may be impossible to replicate using .NET's
Uri
(#52628, #58057).For example, it is currently not possible to send
/foo?A=%42
withHttpClient
, asUri
will convert it to/foo?A=B
.I propose adding a
UriCreationOptions
type and actor
/TryCreate
overload to consume it, serving as the extension point for futureUri
customizability.Uri
has support for implicitly converting a file path into afile://
uri./foo
is a valid Unix absolute file path and support for Unix paths is limited to non-Windows platforms.This can create confusion in cases like
Uri.TryCreate("/foo", UriKind.Absolute)
where the behavior depends on the platform.Given an extension point like
UriCreationOptions
is available, I propose adding anAllowImplicitFilePaths
flag to it.API Proposal
Alternative names for
DangerousUseRawPathAndQuery
:DangerousUseRawTarget
DangerousDisableCanonicalization
Behavior of
DangerousUseRawPathAndQuery
is such that we try not to be opinionated as much as possible:Path
/Query
is skipped, we assume they already are in the “perfect format”%20
)%41
won't be turned intoA
)/../
or/./
will be kept)#
and anything following it is attributed to thePath
orQuery
#
literal as part ofPathAndQuery
Path
,Query
,PathAndQuery
will return the value as-isPath
/PathAndQuery
start with/
, that is left up to the userDangerousUseRawPathAndQuery
may only be equal to Uris with the same flagGetComponents
API will ignore theUriFormat
argument (valuesUriEscaped
,Unescaped
,SafeUnescaped
) forPath
&Query
componentsAPI Usage
Alternative API
Instead of a
readonly struct
, makeUriCreationOptions
an enumAllowImplicitFilePaths
would have to beDontAllowImplicitFilePaths
) to match correctly defaultsUriCreationOptions
we can ensure it's always in a valid state (e.g. validUriKind
)Instead of a
DangerousUseRawPathAndQuery
flag, expose granular options controlling specific transformationsUnescapeUnreservedCharacters
,CompressDotSegments
Risks
Setting
DangerousUseRawPathAndQuery
means no validation/transformation of the input will take place past the authority.If the input is not already in the correct format, HTTP requests using such a Uri may be malformed.
For example:
%20
The text was updated successfully, but these errors were encountered: