Skip to content

[Breaking change]: Uri length limits have been removed #47602

@MihaZupan

Description

@MihaZupan

Description

Methods that create Uri instances (constructors and TryCreate factory methods) have historically limited the length of the Uri string to around 65k characters (exact limits varied slightly depending on the input format).

As of .NET 10 preview 7, these limits have been lifted such that there is practically no upper bound on how long Uris can be. For example, they may now contain paths or queries megabytes long.

PR: dotnet/runtime#117287

Version

.NET 10 Preview 7

Previous behavior

It was previously not possible to create a Uri instance whose length exceeded around 65k characters.
Code like

new Uri($"https://host/{new string('a', 100_000)}")

previously threw a UriFormatException: "Invalid URI: The Uri string is too long.".

New behavior

Uri instances containing large amounts of data can now be created.

string largeQuery = ...;
return new Uri($"https://someService/?query={Uri.EscapeDataString(largeQuery)}");

Note that the removed restrictions mainly apply to paths/queries/fragments as the most practical components to carry large amounts of data. Components such as the scheme and host may still enforce some length limits. Practical limitations as you approach the length limits of string also apply, so you may not (nor should you) use Uri to represent a 10 GB file.

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

Most HTTP servers enforce strict length restrictions on URLs they are willing to accept in requests, generally much lower than Uri's existing limits.
However, since Uri is the de facto exchange type in .NET for Uri-like information, the previous limits limited its use in some scenarios without good workarounds aside from removing the use of Uri throughout API contracts.

Main scenarios for large Uri are:

  • data: uris, which contain arbitrary binary blobs encoded in Base64. These may be transmitted outside of the HTTP request line, e.g. they may be part of the request body, and can therefore be arbitrarily large. Uri may now be used to represent data Uris containing larger files.
  • Large query strings. Uri is often used as an exchange type between systems even if it will never be sent as part of an HTTP request. User request information is often encoded as part of the query string, so the new behavior enables such scenarios even as the amount of data grows.

Recommended action

For the majority of users, there is no action required.

If you are relying on Uri imposing such length restrictions as part of your input validation, you must now perform length checking yourself, preferably as a step before you construct the Uri instance.
As most HTTP servers are enforcing much stricter length limits in practice, very long inputs were already likely to result in failures when sent as part of an HTTP request. You may find that your scenario would benefit from performing even stricter length validation than Uri had done previously.

Feature area

Networking, Core .NET libraries

Affected APIs

All Uri constructors and all Uri.TryCreate overloads.

By extension also all Uri members that return information about the Uri instance, such as string AbsolutePath, string AbsoluteUri, string PathAndQuery, ...


Associated WorkItem - 475890

Metadata

Metadata

Assignees

Labels

📌 seQUESTeredIdentifies that an issue has been imported into Quest.breaking-changeIndicates a .NET Core breaking change

Type

No type

Projects

Status

🔖 Ready

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions