Skip to content

Fix preserving %2F at HTTP/1 absolute-form request#65930

Open
DeagleGross wants to merge 6 commits intodotnet:mainfrom
DeagleGross:dmkorolev/kestrel-absolute-form-path-canonicalization
Open

Fix preserving %2F at HTTP/1 absolute-form request#65930
DeagleGross wants to merge 6 commits intodotnet:mainfrom
DeagleGross:dmkorolev/kestrel-absolute-form-path-canonicalization

Conversation

@DeagleGross
Copy link
Member

Fixes an inconsistency in HTTP/1.1 request-target parsing where %2F in the path produces different
HttpRequest.Path values depending on the request-target form:

Request Before After
GET /a%2Fb (origin-form) /a%2Fb /a%2Fb
GET http://host/a%2Fb (absolute-form) /a/b /a%2Fb

DeagleGross and others added 4 commits March 23, 2026 19:41
…ute-form

When processing HTTP/1.1 absolute-form request targets (e.g.,
GET http://host/a%2Fb), Kestrel used Uri.LocalPath to extract the path,
which decodes %2F to '/'. This differed from origin-form handling which
uses PathDecoder.DecodePath that deliberately preserves %2F.

Replace Uri.LocalPath with Uri.AbsolutePath (which preserves percent-
encoding) followed by PathDecoder.DecodePath, ensuring both request-
target forms produce identical HttpRequest.Path values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ute-form

When processing HTTP/1.1 absolute-form request targets (e.g.,
GET http://host/a%2Fb), Kestrel used Uri.LocalPath to extract the path,
which decodes %2F to '/'. This differed from origin-form handling which
uses PathDecoder.DecodePath that deliberately preserves %2F.

Replace Uri.LocalPath with Uri.AbsolutePath (which preserves percent-
encoding) followed by PathDecoder.DecodePath, ensuring both request-
target forms produce identical HttpRequest.Path values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
https://github.com/DeagleGross/aspnetcore into dmkorolev/kestrel-absolute-form-path-canonicalization

# Conflicts:
#	src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs
@DeagleGross DeagleGross self-assigned this Mar 23, 2026
@DeagleGross DeagleGross requested a review from halter73 as a code owner March 23, 2026 19:27
Copilot AI review requested due to automatic review settings March 23, 2026 19:27
@DeagleGross DeagleGross added the area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions label Mar 23, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an inconsistency in Kestrel HTTP/1.1 request-target parsing so that an encoded slash (%2F) is preserved in HttpRequest.Path for absolute-form targets, matching origin-form (and aligning with HTTP/2/3 path decoding behavior).

Changes:

  • Add StartLineTests coverage for %2F preservation in both origin-form and absolute-form request-targets.
  • Update Http1Connection.OnAbsoluteFormTarget to derive Path via PathDecoder.DecodePath (using Uri.AbsolutePath) instead of uri.LocalPath, avoiding %2F being decoded to /.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/Servers/Kestrel/Core/test/StartLineTests.cs Adds test cases validating %2F stays encoded in Path for origin-form and absolute-form.
src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs Switches absolute-form path materialization from Uri.LocalPath to PathDecoder.DecodePath over Uri.AbsolutePath to preserve %2F.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants