6.45The ForwardAttribute Forwarding Attribute
To simplify forwarding operations, the framework provides the convenient [Forward] controller action forwarding attribute. Compared to manually calling the HttpContext Forward extension methods, this attribute significantly reduces repetitive hardcoding. The following is an example of using the [Forward] attribute:
[ApiController][Route("[controller]/[action]")]public class GetStartController : ControllerBase{ /// <summary> /// Forwards/proxies to the website /// </summary> /// <returns></returns> [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching [Forward("https://github.com", AllowedHosts = ["*"])] public Task<IActionResult?> ForwardToWebSite() { throw new NotImplementedException(); } /// <summary> /// Forwards/proxies to the image /// </summary> /// <returns></returns> [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching [Forward("https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1u7RJI.img?w=584&h=326&m=6", AllowedHosts = ["*"])] public Task<IActionResult?> ForwardToImage() { throw new NotImplementedException(); } /// <summary> /// Forwards/proxies to the file /// </summary> /// <returns></returns> [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] // Disable browser caching [Forward("https://download.visualstudio.microsoft.com/download/pr/a17b907f-8457-45a8-90db-53f2665ee49e/49bccd33593ebceb2847674fe5fd768e/aspnetcore-runtime-8.0.10-win-x64.exe", AllowedHosts = ["*"])] public Task<IActionResult?> ForwardToDownload() { throw new NotImplementedException(); } /// <summary> /// Forwards/proxies to the form /// </summary> /// <param name="id"></param> /// <param name="model"></param> /// <returns></returns> [HttpPost] [Forward("https://localhost:7044/HttpRemote/AddForm", AllowedHosts = ["*"])] public Task<YourRemoteFormResult?> ForwardToForm(int id, [FromForm] YourRemoteFormModel model) { throw new NotImplementedException(); } /// <summary> /// Forwards/proxies to the string /// </summary> /// <returns></returns> [HttpGet] [Forward("https://localhost:7044/GetStart/PostRawString", AllowedHosts = ["*"])] public Task<string> ForwardToString() { throw new NotImplementedException(); } /// <summary> /// Forwards/proxies to no return value /// </summary> /// <returns></returns> [HttpGet] [Forward("https://localhost:7044/GetStart/PostRawString", AllowedHosts = ["*"])] public Task ForwardToVoid() { throw new NotImplementedException(); }}In the code above, we only need to add the [Forward] attribute to the controller actions that need to be forwarded and specify the target URL. The framework automatically handles the forwarding logic, so no implementation code needs to be written in the method body (typically a NotImplementedException is thrown to indicate that this is a forwarding operation handled automatically by the framework). This approach is particularly convenient in microservice applications, greatly simplifying code writing and maintenance.
ForwardAttribute contains the following properties:
- Properties:
RequestUri: the forwarding address (typestring).Method: the forwarding method. If not set, the current request method is automatically adopted as the forwarding method (typeHttpMethod).HttpClientName: the configuration name of theHttpClientinstance, with a default value ofnull(typestring).CompletionOption: indicates how the response content is handled, with a default value ofResponseHeadersRead(typeHttpCompletionOption).AllowedHosts: the allowlist of target hosts permitted for forwarding (typestring[]?).
Used to defend against Server-Side Request Forgery (SSRF) attacks. Forwarding is permitted only when the target address's host (including port and protocol) matches one of the entries in the list.
Supported formats (matching is case-insensitive):"furion.net"– hostname only, matches the default ports (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 only any port of the specified protocol."*"– global wildcard, allows any host and protocol (completely bypasses validation, high risk).
If not configured or empty, all target addresses specified through theX-Forward-Torequest header will be rejected to prevent unauthorized forwarding. It is recommended to use precise rules whenever possible, and only open wildcards to fully trusted sources.
WithQueryParameters: whether to forward query parameters (URLparameters), default valuetrue(typebool).WithRequestHeaders: whether to forward request headers, default valuetrue(typebool).WithResponseStatusCode: whether to forward the response status code, default valuetrue(typebool).WithResponseHeaders: whether to forward response headers, default valuetrue(typebool).WithResponseContentHeaders: whether to forward response content headers, default valuetrue(typebool).ResetHostRequestHeader: whether to reset theHostrequest header, default valuefalse(typebool).IgnoreQueryParameters: the list of query parameters (URLparameters) to skip when forwarding (typestring[]?).IgnoreRequestHeaders: the list of request headers to skip when forwarding (typestring[]?).IgnoreResponseHeaders: the list of response headers to skip when forwarding (typestring[]?).