Skip to content

Commit bf991f6

Browse files
committed
Fix up handling for forwarded headers
1 parent 2f2b731 commit bf991f6

File tree

2 files changed

+56
-1
lines changed

2 files changed

+56
-1
lines changed

src/OpenApi/src/Services/OpenApiDocumentService.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,26 @@ internal List<OpenApiServer> GetOpenApiServers(HttpRequest? httpRequest = null)
199199
{
200200
if (httpRequest is not null)
201201
{
202-
var serverUrl = UriHelper.BuildAbsolute(httpRequest.Scheme, httpRequest.Host, httpRequest.PathBase);
202+
// Handle forwarded headers directly if present
203+
var scheme = httpRequest.Headers.GetCommaSeparatedValues("X-Forwarded-Proto") is [var forwardedScheme, ..]
204+
? forwardedScheme
205+
: httpRequest.Scheme;
206+
207+
var host = httpRequest.Headers.GetCommaSeparatedValues("X-Forwarded-Host") is [var forwardedHost, ..]
208+
? forwardedHost
209+
: httpRequest.Host.Value;
210+
211+
var hostString = new HostString(host);
212+
var serverUrl = UriHelper.BuildAbsolute(scheme, hostString, httpRequest.PathBase);
213+
203214
return [new OpenApiServer { Url = serverUrl }];
204215
}
205216
else
206217
{
207218
return GetDevelopmentOpenApiServers();
208219
}
209220
}
221+
210222
private List<OpenApiServer> GetDevelopmentOpenApiServers()
211223
{
212224
if (hostEnvironment.IsDevelopment() &&

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

+43
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,47 @@ public void GetOpenApiServers_HandlesServerAddressFeatureWithNoValues()
146146
// Assert
147147
Assert.Empty(servers);
148148
}
149+
150+
[Theory]
151+
[InlineData("https", "proxy-server.com", "https://proxy-server.com/original-path")]
152+
[InlineData("http", "proxy:8080", "http://proxy:8080/original-path")]
153+
[InlineData("https", "proxy.example.org", "https://proxy.example.org/original-path")]
154+
public void GetOpenApiServers_HandlesForwardedHeaders(string forwardedProto, string forwardedHost, string expectedUrl)
155+
{
156+
// Arrange
157+
var hostEnvironment = new HostingEnvironment
158+
{
159+
ApplicationName = "TestApplication",
160+
EnvironmentName = "Production"
161+
};
162+
var docService = new OpenApiDocumentService(
163+
"v1",
164+
new Mock<IApiDescriptionGroupCollectionProvider>().Object,
165+
hostEnvironment,
166+
GetMockOptionsMonitor(),
167+
new Mock<IKeyedServiceProvider>().Object,
168+
new OpenApiTestServer(["http://localhost:5000"]));
169+
170+
var httpContext = new DefaultHttpContext()
171+
{
172+
Request =
173+
{
174+
// Original values that should be overridden by forwarded headers
175+
Host = new HostString("localhost:5000"),
176+
PathBase = "/original-path",
177+
Scheme = "http"
178+
}
179+
};
180+
181+
// Add forwarded headers
182+
httpContext.Request.Headers["X-Forwarded-Proto"] = forwardedProto;
183+
httpContext.Request.Headers["X-Forwarded-Host"] = forwardedHost;
184+
185+
// Act
186+
var servers = docService.GetOpenApiServers(httpContext.Request);
187+
188+
// Assert
189+
var serverUrl = Assert.Single(servers).Url;
190+
Assert.Equal(expectedUrl, serverUrl);
191+
}
149192
}

0 commit comments

Comments
 (0)