Skip to content

Conversation

andwi
Copy link
Contributor

@andwi andwi commented Jul 6, 2023

Support for X-Forwarded-Prefix in ForwardedHeadersMiddleware

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Adds the option to change PathBase based on the X-Forwarded-Prefix header.

Fixes #23263

@andwi andwi requested review from a team, Tratcher and BrennanConroy as code owners July 6, 2023 19:05
@ghost ghost added area-runtime community-contribution Indicates that the PR has been added by a community member labels Jul 6, 2023
@ghost
Copy link

ghost commented Jul 6, 2023

Thanks for your PR, @andwi. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@andwi
Copy link
Contributor Author

andwi commented Jul 6, 2023

@dotnet-policy-service agree

@adityamandaleeka
Copy link
Member

Thanks for the contribution @andwi! Since this change affects public API, it will need to go through the API review process (but in this case, the API change is so small and follows the existing pattern so it will be super easy!).

To get that kicked off, can you please add a comment on the issue (#23263) with the proposed API change, following the template here? https://github.com/dotnet/aspnetcore/issues/new?assignees=&labels=api-suggestion&template=30_api_proposal.md&title=

Tag me once you've done that and we can mark the issue as being ready for us to review during the next API review session.

BTW the CI failure was unrelated (message is below and I hadn't seen this one before... seems like something went wrong when building the installers @wtgodbe?) so I reran the failing leg.

src\Installers\Windows\WindowsHostingBundle\SharedFramework.wxs(39,0): error LGHT0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The system cannot find the file 'D:\a\_work\1\s\artifacts\installers\Release\\aspnetcore-runtime-8.0.0-ci-win-x64.exe'

@wtgodbe
Copy link
Member

wtgodbe commented Jul 7, 2023

BTW the CI failure was unrelated (message is below and I hadn't seen this one before... seems like something went wrong when building the installers @wtgodbe?) so I reran the failing leg.

Looks like an ordering issue - I don't think I've seen that one before, I'll keep an eye out for it in future builds

@andwi
Copy link
Contributor Author

andwi commented Jul 8, 2023

Updated the logic for setting the X-Original-Prefix header to make sure empty string is replaced with /

@ghost
Copy link

ghost commented Jul 21, 2023

Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime.
To make sure no conflicting changes have occurred, please rerun validation before merging. You can do this by leaving an /azp run comment here (requires commit rights), or by simply closing and reopening.

@ghost ghost added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Jul 21, 2023
@adityamandaleeka
Copy link
Member

Still waiting on API review for this one.

Comment on lines 371 to 372
requestHeaders[_options.OriginalPrefixHeaderName] =
request.PathBase.HasValue ? request.PathBase.ToString() : "/";
Copy link
Member

Choose a reason for hiding this comment

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

"/" and "" are not equivalent paths, especially for PathBase. PathBase is commonly empty. I understand that's awkward to represent in this collection. It might be better to skip adding the original value when empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed so that X-Original-Prefix is only added if PathBase has value

requestHeaders.Remove(_options.ForwardedPrefixHeaderName);
}

request.PathBase = PathString.FromUriComponent(currentValues.Prefix.TrimEnd('/'));
Copy link
Member

Choose a reason for hiding this comment

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

TrimEnd shouldn't be needed, pass the given value through. PathString has built in logic to avoid duplicate slashes when combined with another PathString (PathBase + Path).

public PathString Add(PathString other)
{
if (HasValue &&
other.HasValue &&
Value[^1] == '/')
{
// If the path string has a trailing slash and the other string has a leading slash, we need
// to trim one of them.
var combined = string.Concat(Value.AsSpan(), other.Value.AsSpan(1));
return new PathString(combined);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted

@@ -1116,4 +1121,137 @@ public async Task ForwardersWithDirectOptionsRunsTwice(int limit, string header,
Assert.Equal(expectedScheme, context.Request.Scheme);
Assert.Equal(remainingHeader, context.Request.Headers["X-Forwarded-Proto"].ToString());
}

[Theory]
[InlineData("", "/foo", "/foo", "/")]
Copy link
Member

Choose a reason for hiding this comment

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

Add /foo/bar as a multi-segment test case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added multi-segment test case

@adityamandaleeka
Copy link
Member

@andwi The API has been approved #23263 (comment)

@Tratcher Looks like your comments have been addressed. Any more feedback or is this ready for merge?

if (forwardedPrefix!.Length > entriesConsumed)
{
// Truncate the consumed header values
requestHeaders[_options.ForwardedPrefixHeaderName] = forwardedPrefix.Take(forwardedPrefix.Length - entriesConsumed).ToArray();
Copy link
Member

Choose a reason for hiding this comment

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

Why is this using LINQ? Let's aim to avoid all temporary allocations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why is this using LINQ?

Just followed the existing pattern in the class.

Have pushed new commits that change all the cases where header values are truncated to use a new helper method that uses Array.Copy instead of LINQ.

@amcasey
Copy link
Member

amcasey commented Aug 1, 2023

Looks like API review signed off: #23263. Good to go?

@adityamandaleeka
Copy link
Member

Thanks @andwi

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 community-contribution Indicates that the PR has been added by a community member pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for x-forwarded-prefix
7 participants