Skip to content

HttpSys request header dictionary does not remove headers when Remove() is called #43230

@markalward

Description

@markalward

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When using the HttpSys server, the request header dictionary (HttpRequest.Headers) behaves unexpectedly when trying to remove a header using IHeaderDictionary.Remove(). The Remove() method fails to remove some headers, even when those headers are present in the request - when enumerating the collection after the call to Remove(), the original header is still returned.

Expected Behavior

If a header is present in the header dictionary, it should be removed from the collection when Remove() is called. Subsequent operations on the collection (enumeration, indexer, ContainsKey, etc.) should not return the removed header.

Steps To Reproduce

Create an ASP.NET Core app, using HttpSys as the server. The code below reproduces the issue.

in Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.Run(httpContext =>
    {
        var headers = httpContext.Request.Headers;
        bool removed = headers.Remove("Connection");

        Debug.WriteLine(removed); // prints 'false'

        string connection = headers["Connection"];
        Debug.WriteLine(connection); // prints 'Close'

        return Task.CompletedTask;
    });
}

in Program.cs:

var builder = Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseHttpSys(options =>
        {
            options.UrlPrefixes.Add("http://+:5000/");
        });

        webBuilder.UseStartup<Startup>();
    });

var app = builder.Build();
app.Run();

This curl command was used:
curl --verbose --header Connection:Close http://localhost:5000/

Note that a number of other headers such as 'Accept-Encoding' also reproduce the issue.

Exceptions (if any)

No response

.NET Version

net6.0

Anything else?

Relevant line of code in RequestHeaders implementation: https://github.com/dotnet/aspnetcore/blob/main/src/Shared/HttpSys/RequestProcessing/RequestHeaders.Generated.cs#L1860

If the _Connection field hasn't been populated at this point in the code, PropertiesTryRemove() returns false and the header isn't removed. Later on, if the same header is retrieved using PropertiesTryGetValue(), the actual header value is retrieved by calling NativeRequestContext.GetKnownHeader().

Other details:

  • This issue appears to affect all the 'known' headers listed in the RequestHeaders.Generated.cs file.
  • The issue does not repro if the header was previously loaded, due to enumerating the header dictionary or retrieving the header using request.Headers["Connection"].
  • The issue does not repro on Kestrel.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractionsbugThis issue describes a behavior which is not expected - a bug.help wantedUp for grabs. We would accept a PR to help resolve this issue

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions