6.38HttpContext Forwarding and Proxying
HttpContext forwarding refers to the process, within an ASP.NET Core application, of forwarding the context information of one HTTP request (including request headers, request content, query strings, response headers, response content, and so on) from one request to another internal request or service. This technique allows developers to redirect a request to another processing point without changing the client request, thereby implementing request proxying or routing functionality.
Use cases for HttpContext forwarding:
API Gatewaypattern: Acts as the entry point for all external requests, routing requests to the correct backend services.- Load balancing and failover: Forwards requests to other available service instances to ensure system stability and reliability.
- Request logging and auditing: Records request information to a logging system or auditing service for easier monitoring and debugging.
- Security filtering and validation: Checks the request's authentication information and permissions during forwarding to ensure the legitimacy of the request.
- A/B testing and blue-green deployment: Routes a portion of traffic to a new version of a service to gradually validate new features.
- Cross-origin request handling: Handles cross-origin requests to ensure that requests execute successfully.
Before using HttpContext for forwarding operations, make sure you have completed the following two steps:
- Register and enable the
IHttpContextAccessorservice.
Register and enable the IHttpContextAccessor service in the Startup.cs or Program.cs file, and configure the forwarding target allowlist.
services.AddHttpContextAccessor(); // Not required with the Furion framework (already injected by default)// Globally configure HttpContext forwarding configuration optionsservices.Configure<HttpContextForwardOptions>(options =>{ // Allowlist of target hosts allowed for forwarding; must be configured explicitly. If not configured or empty, any forwarding via the X-Forward-To header will be rejected options.AllowedHosts = ["*"]; // "*" means allow all hosts and protocols (high risk; recommended only in trusted environments)});Detailed explanation of the AllowedHosts allowlist rules:
"furion.net"— Hostname only; matches the default port (80/443) of any protocol (http/https)."furion.net:8080"— Host + port; matches the specified port of any protocol."furion.net:*"— Host + port wildcard; matches any port under any protocol."https://furion.net"— Protocol + host; matches only the default port of the specified protocol."http://furion.net:8080"— Protocol + host + port; exact match."https://furion.net:*"— Protocol + host + port wildcard; matches any port of the specified protocol only."[::1]"—IPv6host (wrapped in square brackets); matches the default port of any protocol."[::1]:8080"—IPv6host + port; matches the specified port of any protocol."[::1]:*"—IPv6host + port wildcard; matches any port under any protocol."http://[2001:db8::1]:8080"— Protocol + IPv6 host + port; exact match."*"— Global wildcard; allows any host and protocol (completely bypasses all host validation).
- Enable the request body buffering middleware to support repeated reading of the request content.
app.UseEnableBuffering();- (Optional) If a certificate error such as
The SSL connection could not be established, see inner exception.occurs during forwarding, you can add the following configuration to ignoreSSLcertificate validation:
// Default client configurationservices.AddHttpClient(string.Empty) .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { // Ignore SSL certificate validation ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors, SslProtocols = HttpRemoteUtility.AllSslProtocols });// If using SocketsHttpHandler, you can ignore SSL certificate validation with the following configurationservices.AddHttpClient(string.Empty) .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler() { SslOptions = new SslClientAuthenticationOptions { // Ignore SSL certificate validation RemoteCertificateValidationCallback = HttpRemoteUtility.IgnoreSocketSslErrors, EnabledSslProtocols = HttpRemoteUtility.AllSslProtocols }, });The following is a simple example showing how to implement HttpContext forwarding in ASP.NET Core:
[ApiController][Route("[controller]/[action]")]public class GetStartController(IHttpRemoteService httpRemoteService, IHttpContextAccessor httpContextAccessor) : ControllerBase{ // Forward proxy to a website [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching public Task<IActionResult?> ForwardToWebSite() { return httpContextAccessor.HttpContext.ForwardAsResultAsync("https://github.com"); } // Forward proxy to an image [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching public Task<IActionResult?> ForwardToImage() { return httpContextAccessor.HttpContext.ForwardAsResultAsync( "https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1u7RJI.img?w=584&h=326&m=6"); } // Forward proxy to a download [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching public Task<IActionResult?> ForwardToDownload() { return httpContextAccessor.HttpContext.ForwardAsResultAsync( "https://download.visualstudio.microsoft.com/download/pr/a17b907f-8457-45a8-90db-53f2665ee49e/49bccd33593ebceb2847674fe5fd768e/aspnetcore-runtime-8.0.10-win-x64.exe"); } // Forward proxy to a form [HttpPost] public Task<YourRemoteFormResult?> ForwardToForm(int id, [FromForm] YourRemoteFormModel model) { return httpContextAccessor.HttpContext.ForwardAsAsync<YourRemoteFormResult>( "https://localhost:7044/HttpRemote/AddForm"); }}With HttpContext forwarding, you can combine Middleware technology in ASP.NET Core applications to implement flexible request routing and handling mechanisms, suitable for various scenarios such as API Gateway, load balancing, request logging, security validation, and more.