Api docs for HttpOverrides (#26530)

* Api docs for HttpOverrides

* Update ForwardedHeadersExtensions.cs

* Update ForwardedHeadersOptions.cs

* Feedback

* Add more details

Co-authored-by: Pranav K <prkrishn@hotmail.com>
This commit is contained in:
John Luo 2020-10-02 13:42:18 -07:00 committed by GitHub
parent 0a52bb721c
commit ce2e3bc723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 115 additions and 22 deletions

View File

@ -5,13 +5,31 @@ using System;
namespace Microsoft.AspNetCore.HttpOverrides
{
/// <summary>
/// Flags for controlling which forwarders are processed.
/// </summary>
[Flags]
public enum ForwardedHeaders
{
/// <summary>
/// Do not process any forwarders
/// </summary>
None = 0,
/// <summary>
/// Process X-Forwarded-For, which identifies the originating IP address of the client.
/// </summary>
XForwardedFor = 1 << 0,
/// <summary>
/// Process X-Forwarded-Host, which identifies the original host requested by the client.
/// </summary>
XForwardedHost = 1 << 1,
/// <summary>
/// Process X-Forwarded-Proto, which identifies the protocol (HTTP or HTTPS) the client used to connect.
/// </summary>
XForwardedProto = 1 << 2,
/// <summary>
/// Process X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto.
/// </summary>
All = XForwardedFor | XForwardedHost | XForwardedProto
}
}

View File

@ -7,15 +7,22 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Extension methods for enabling <see cref="ForwardedHeadersMiddleware"/>.
/// </summary>
public static class ForwardedHeadersExtensions
{
private const string ForwardedHeadersAdded = "ForwardedHeadersAdded";
/// <summary>
/// Forwards proxied headers onto current request
/// Applies forwarded headers to their matching fields on the current request.
/// <para>
/// By convention, HTTP proxies forward information from the client in well-known HTTP headers.
/// The <see cref="ForwardedHeadersMiddleware"/> reads these headers and fills in the associated fields on HttpContext.
/// </para>
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
/// <param name="builder">The <see cref="IApplicationBuilder" />.</param>
/// <returns>A reference to <paramref name="builder" /> after the operation has completed.</returns>
public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder)
{
if (builder == null)
@ -35,11 +42,15 @@ namespace Microsoft.AspNetCore.Builder
}
/// <summary>
/// Forwards proxied headers onto current request
/// Applies forwarded headers to their matching fields on the current request.
/// <para>
/// By convention, HTTP proxies forward information from the client in well-known HTTP headers.
/// The <see cref="ForwardedHeadersMiddleware"/> reads these headers and fills in the associated fields on HttpContext.
/// </para>
/// </summary>
/// <param name="builder"></param>
/// <param name="builder">The <see cref="IApplicationBuilder" />.</param>
/// <param name="options">Enables the different forwarding options.</param>
/// <returns></returns>
/// <returns>A reference to <paramref name="builder" /> after the operation has completed.</returns>
public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder, ForwardedHeadersOptions options)
{
if (builder == null)

View File

@ -15,6 +15,9 @@ using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.HttpOverrides
{
/// <summary>
/// A middleware for forwarding proxied headers onto the current request.
/// </summary>
public class ForwardedHeadersMiddleware
{
private static readonly bool[] HostCharValidity = new bool[127];
@ -62,6 +65,12 @@ namespace Microsoft.AspNetCore.HttpOverrides
}
}
/// <summary>
/// Create a new <see cref="ForwardedHeadersMiddleware"/>.
/// </summary>
/// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> used for logging.</param>
/// <param name="options">The <see cref="ForwardedHeadersOptions"/> for configuring the middleware.</param>
public ForwardedHeadersMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<ForwardedHeadersOptions> options)
{
if (next == null)
@ -137,12 +146,20 @@ namespace Microsoft.AspNetCore.HttpOverrides
|| string.Equals("0.0.0.0", host, StringComparison.Ordinal)); // IPv4 Any
}
/// <summary>
/// Executes the middleware.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/> for the current request.</param>
public Task Invoke(HttpContext context)
{
ApplyForwarders(context);
return _next(context);
}
/// <summary>
/// Forward the proxied headers to the given <see cref="HttpContext"/>.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
public void ApplyForwarders(HttpContext context)
{
// Gather expected headers.

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
@ -7,40 +7,46 @@ using Microsoft.AspNetCore.HttpOverrides;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Options for <see cref="ForwardedHeadersMiddleware"/>
/// </summary>
public class ForwardedHeadersOptions
{
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XForwardedForHeaderName"/>
/// Gets or sets the header used to retrieve the originating client IP. Defaults to the value specified by
/// <see cref="ForwardedHeadersDefaults.XForwardedForHeaderName"/>.
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersDefaults"/>
public string ForwardedForHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedForHeaderName;
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XForwardedHostHeaderName"/>
/// Gets or sets the header used to retrieve the original value of the Host header field.
/// Defaults to the value specified by <see cref="ForwardedHeadersDefaults.XForwardedHostHeaderName"/>
/// </summary>
/// <seealso cref="ForwardedHeadersDefaults"/>
public string ForwardedHostHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedHostHeaderName;
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XForwardedProtoHeaderName"/>
/// Gets or sets the header used to retrieve the value for the originating scheme (HTTP/HTTPS).
/// Defaults to the value specified by <see cref="ForwardedHeadersDefaults.XForwardedProtoHeaderName"/>
/// </summary>
/// <seealso cref="ForwardedHeadersDefaults"/>
public string ForwardedProtoHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedProtoHeaderName;
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XOriginalForHeaderName"/>
/// Gets or sets the header used to store the original value of client IP before applying forwarded headers.
/// Defaults to the value specified by <see cref="ForwardedHeadersDefaults.XOriginalForHeaderName"/>
/// </summary>
/// <seealso cref="ForwardedHeadersDefaults"/>
public string OriginalForHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalForHeaderName;
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XOriginalHostHeaderName"/>
/// Gets or sets the header used to store the original value of the Host header field before applying forwarded headers.
/// Defaults to the value specified by <see cref="ForwardedHeadersDefaults.XOriginalHostHeaderName"/>
/// </summary>
/// <seealso cref="ForwardedHeadersDefaults"/>
public string OriginalHostHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalHostHeaderName;
/// <summary>
/// Use this header instead of <see cref="ForwardedHeadersDefaults.XOriginalProtoHeaderName"/>
/// Gets or sets the header used to store the original scheme (HTTP/HTTPS) before applying forwarded headers.
/// Defaults to the value specified by <see cref="ForwardedHeadersDefaults.XOriginalProtoHeaderName"/>
/// </summary>
/// <seealso cref="ForwardedHeadersDefaults"/>
public string OriginalProtoHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalProtoHeaderName;

View File

@ -7,10 +7,15 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Extension methods for enabling <see cref="HttpMethodOverrideMiddleware"/>.
/// </summary>
public static class HttpMethodOverrideExtensions
{
/// <summary>
/// Allows incoming POST request to override method type with type specified in header.
/// Allows incoming POST request to override method type with type specified in header. This middleware
/// is used when a client is limited to sending GET or POST methods but wants to invoke other HTTP methods.
/// By default, the X-HTTP-Method-Override request header is used to specify the HTTP method being tunneled.
/// </summary>
/// <param name="builder">The <see cref="IApplicationBuilder"/> instance this method extends.</param>
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder)
@ -24,10 +29,13 @@ namespace Microsoft.AspNetCore.Builder
}
/// <summary>
/// Allows incoming POST request to override method type with type specified in form.
/// Allows incoming POST request to override method type with type specified in form. This middleware
/// is used when a client is limited to sending GET or POST methods but wants to invoke other HTTP methods.
/// </summary>
/// <param name="builder">The <see cref="IApplicationBuilder"/> instance this method extends.</param>
/// <param name="options">The <see cref="HttpMethodOverrideOptions"/>.</param>
/// <param name="options">
/// The <see cref="HttpMethodOverrideOptions"/> which indicates which form type specifies the override method.
/// </param>
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, HttpMethodOverrideOptions options)
{
if (builder == null)

View File

@ -9,12 +9,20 @@ using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.HttpOverrides
{
/// <summary>
/// A middleware for overriding the HTTP method of an incoming POST request.
/// </summary>
public class HttpMethodOverrideMiddleware
{
private const string xHttpMethodOverride = "X-Http-Method-Override";
private readonly RequestDelegate _next;
private readonly HttpMethodOverrideOptions _options;
/// <summary>
/// Create a new <see cref="HttpMethodOverrideMiddleware"/>.
/// </summary>
/// <param name="next">The <see cref="RequestDelegate"/> representing the next middleware in the pipeline.</param>
/// <param name="options">The <see cref="HttpMethodOverrideOptions"/> for configuring the middleware.</param>
public HttpMethodOverrideMiddleware(RequestDelegate next, IOptions<HttpMethodOverrideOptions> options)
{
if (next == null)
@ -29,6 +37,10 @@ namespace Microsoft.AspNetCore.HttpOverrides
_options = options.Value;
}
/// <summary>
/// Executes the middleware.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/> for the current request.</param>
public async Task Invoke(HttpContext context)
{
if (HttpMethods.IsPost(context.Request.Method))

View File

@ -1,8 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.HttpOverrides;
namespace Microsoft.AspNetCore.Builder
{
/// <summary>
/// Options for configuring <see cref="HttpMethodOverrideMiddleware"/>
/// </summary>
public class HttpMethodOverrideOptions
{
/// <summary>

View File

@ -1,12 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Net;
namespace Microsoft.AspNetCore.HttpOverrides
{
/// <summary>
/// A representation of an IP network based on CIDR notation.
/// </summary>
public class IPNetwork
{
/// <summary>
/// Create a new <see cref="IPNetwork"/> with the specified <see cref="IPAddress"/> and prefix length.
/// </summary>
/// <param name="prefix">The <see cref="IPAddress"/>.</param>
/// <param name="prefixLength">The prefix length.</param>
public IPNetwork(IPAddress prefix, int prefixLength)
{
Prefix = prefix;
@ -15,6 +23,9 @@ namespace Microsoft.AspNetCore.HttpOverrides
Mask = CreateMask();
}
/// <summary>
/// Get the <see cref="IPAddress"/> that represents the prefix for the network.
/// </summary>
public IPAddress Prefix { get; }
private byte[] PrefixBytes { get; }
@ -26,6 +37,11 @@ namespace Microsoft.AspNetCore.HttpOverrides
private byte[] Mask { get; }
/// <summary>
/// Determine whether a given The <see cref="IPAddress"/> is part of the IP network.
/// </summary>
/// <param name="address">The <see cref="IPAddress"/>.</param>
/// <returns><see langword="true"/> if the <see cref="IPAddress"/> is part of the IP network. Otherwise, <see langword="false"/>.</returns>
public bool Contains(IPAddress address)
{
if (Prefix.AddressFamily != address.AddressFamily)

View File

@ -6,7 +6,7 @@
* HTTP method override header.</Description>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<IsAspNetCoreApp>true</IsAspNetCoreApp>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<NoWarn>$(NoWarn.Replace('1591', ''))</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore;proxy;headers;xforwarded</PackageTags>
<IsPackable>false</IsPackable>

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Net;
using Xunit;