Skip to content

Commit db8893b

Browse files
Exclude some headers from OpenAPI parameters (#57328)
Do not include the `Accept`, `Authorization` and `Content-Type` headers in OpenAPI operation parameters. Resolves #57305.
1 parent a360882 commit db8893b

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

src/OpenApi/src/Services/OpenApiDocumentService.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Collections.Frozen;
45
using System.ComponentModel;
56
using System.ComponentModel.DataAnnotations;
67
using System.Diagnostics;
@@ -22,6 +23,7 @@
2223
using Microsoft.Extensions.DependencyInjection;
2324
using Microsoft.Extensions.Hosting;
2425
using Microsoft.Extensions.Options;
26+
using Microsoft.Net.Http.Headers;
2527
using Microsoft.OpenApi.Models;
2628

2729
namespace Microsoft.AspNetCore.OpenApi;
@@ -47,6 +49,8 @@ internal sealed class OpenApiDocumentService(
4749
private readonly Dictionary<string, OpenApiOperationTransformerContext> _operationTransformerContextCache = new();
4850
private static readonly ApiResponseType _defaultApiResponseType = new() { StatusCode = StatusCodes.Status200OK };
4951

52+
private static readonly FrozenSet<string> _disallowedHeaderParameters = new[] { HeaderNames.Accept, HeaderNames.Authorization, HeaderNames.ContentType }.ToFrozenSet(StringComparer.OrdinalIgnoreCase);
53+
5054
internal bool TryGetCachedOperationTransformerContext(string descriptionId, [NotNullWhen(true)] out OpenApiOperationTransformerContext? context)
5155
=> _operationTransformerContextCache.TryGetValue(descriptionId, out context);
5256

@@ -393,9 +397,7 @@ private async Task<OpenApiResponse> GetResponseAsync(
393397
List<OpenApiParameter>? parameters = null;
394398
foreach (var parameter in description.ParameterDescriptions)
395399
{
396-
// Parameters that should be in the request body should not be
397-
// populated in the parameters list.
398-
if (parameter.IsRequestBodyParameter())
400+
if (ShouldIgnoreParameter(parameter))
399401
{
400402
continue;
401403
}
@@ -419,6 +421,24 @@ private async Task<OpenApiResponse> GetResponseAsync(
419421
parameters.Add(openApiParameter);
420422
}
421423
return parameters;
424+
425+
static bool ShouldIgnoreParameter(ApiParameterDescription parameter)
426+
{
427+
if (parameter.IsRequestBodyParameter())
428+
{
429+
// Parameters that should be in the request body should not be
430+
// populated in the parameters list.
431+
return true;
432+
}
433+
else if (parameter.Source == BindingSource.Header && _disallowedHeaderParameters.Contains(parameter.Name))
434+
{
435+
// OpenAPI 3.0 states certain headers are "not allowed" to be defined as parameters.
436+
// See https://github.com/dotnet/aspnetcore/issues/57305 for more context.
437+
return true;
438+
}
439+
440+
return false;
441+
}
422442
}
423443

424444
private static bool IsRequired(ApiParameterDescription parameter)

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiDocumentService/OpenApiDocumentServiceTests.Parameters.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,30 @@ await VerifyOpenApiDocument(builder, document =>
164164
Assert.Null(todosOperation.Parameters);
165165
});
166166
}
167+
168+
[Fact]
169+
public async Task GetOpenApiParameters_SkipsDisallowedHeaders()
170+
{
171+
// Arrange
172+
var builder = CreateBuilder();
173+
174+
// Act
175+
builder.MapGet("/api/accept", ([FromHeader(Name = "Accept")] string value) => { });
176+
builder.MapGet("/api/accept-lower", ([FromHeader(Name = "accept")] string value) => { });
177+
builder.MapGet("/api/authorization", ([FromHeader(Name = "Authorization")] string value) => { });
178+
builder.MapGet("/api/authorization-lower", ([FromHeader(Name = "authorization")] string value) => { });
179+
builder.MapGet("/api/content-type", ([FromHeader(Name = "Content-Type")] string value) => { });
180+
builder.MapGet("/api/content-type-lower", ([FromHeader(Name = "content-type")] string value) => { });
181+
182+
// Assert
183+
await VerifyOpenApiDocument(builder, document =>
184+
{
185+
Assert.Null(document.Paths["/api/accept"].Operations[OperationType.Get].Parameters);
186+
Assert.Null(document.Paths["/api/accept-lower"].Operations[OperationType.Get].Parameters);
187+
Assert.Null(document.Paths["/api/authorization"].Operations[OperationType.Get].Parameters);
188+
Assert.Null(document.Paths["/api/authorization-lower"].Operations[OperationType.Get].Parameters);
189+
Assert.Null(document.Paths["/api/content-type"].Operations[OperationType.Get].Parameters);
190+
Assert.Null(document.Paths["/api/content-type-lower"].Operations[OperationType.Get].Parameters);
191+
});
192+
}
167193
}

0 commit comments

Comments
 (0)