parent
82f15613f2
commit
5e3c7cbbf0
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.23107.0
|
VisualStudioVersion = 14.0.24720.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.HttpOverrides", "src\Microsoft.AspNet.HttpOverrides\Microsoft.AspNet.HttpOverrides.xproj", "{517308C3-B477-4B01-B461-CAB9C10B6928}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.HttpOverrides", "src\Microsoft.AspNet.HttpOverrides\Microsoft.AspNet.HttpOverrides.xproj", "{517308C3-B477-4B01-B461-CAB9C10B6928}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -24,6 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{9587
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ResponseBufferingSample", "samples\ResponseBufferingSample\ResponseBufferingSample.xproj", "{E5C55B80-7827-40EB-B661-32B0E0E431CA}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ResponseBufferingSample", "samples\ResponseBufferingSample\ResponseBufferingSample.xproj", "{E5C55B80-7827-40EB-B661-32B0E0E431CA}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "HttpOverridesSample", "samples\HttpOverridesSample\HttpOverridesSample.xproj", "{7F95478D-E1D4-4A64-BA42-B041591A96EB}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -50,6 +52,10 @@ Global
|
||||||
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -60,5 +66,6 @@ Global
|
||||||
{2363D0DD-A3BF-437E-9B64-B33AE132D875} = {A5076D28-FA7E-4606-9410-FEDD0D603527}
|
{2363D0DD-A3BF-437E-9B64-B33AE132D875} = {A5076D28-FA7E-4606-9410-FEDD0D603527}
|
||||||
{F5F1D123-9C81-4A9E-8644-AA46B8E578FB} = {8437B0F3-3894-4828-A945-A9187F37631D}
|
{F5F1D123-9C81-4A9E-8644-AA46B8E578FB} = {8437B0F3-3894-4828-A945-A9187F37631D}
|
||||||
{E5C55B80-7827-40EB-B661-32B0E0E431CA} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}
|
{E5C55B80-7827-40EB-B661-32B0E0E431CA} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}
|
||||||
|
{7F95478D-E1D4-4A64-BA42-B041591A96EB} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>7f95478d-e1d4-4a64-ba42-b041591a96eb</ProjectGuid>
|
||||||
|
<RootNamespace>HttpOverridesSample</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<DnxInvisibleContent Include="bower.json" />
|
||||||
|
<DnxInvisibleContent Include=".bowerrc" />
|
||||||
|
<DnxInvisibleContent Include="package.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:1658/",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNET_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"commandName": "web",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNET_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Hosting;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.HttpOverrides;
|
||||||
|
|
||||||
|
namespace HttpOverridesSample
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.UseIISPlatformHandler();
|
||||||
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.All;
|
||||||
|
});
|
||||||
|
app.UseHttpMethodOverride();
|
||||||
|
|
||||||
|
app.Run(async (context) =>
|
||||||
|
{
|
||||||
|
foreach (var header in context.Request.Headers)
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync($"{header.Key}: {header.Value}\r\n");
|
||||||
|
}
|
||||||
|
await context.Response.WriteAsync($"Method: {context.Request.Method}\r\n");
|
||||||
|
await context.Response.WriteAsync($"Scheme: {context.Request.Scheme}\r\n");
|
||||||
|
await context.Response.WriteAsync($"RemoteIP: {context.Connection.RemoteIpAddress}\r\n");
|
||||||
|
await context.Response.WriteAsync($"RemotePort: {context.Connection.RemotePort}\r\n");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry point for the application.
|
||||||
|
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"server": "Microsoft.AspNet.Server.Kestrel"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-*",
|
||||||
|
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*",
|
||||||
|
"Microsoft.AspNet.HttpOverrides": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"commands": {
|
||||||
|
"web": "HttpOverridesSample"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"dnx451": { },
|
||||||
|
"dnxcore50": { }
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"wwwroot",
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"publishExclude": [
|
||||||
|
"**.user",
|
||||||
|
"**.vspscc"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
|
||||||
|
</handlers>
|
||||||
|
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" stdoutLogEnabled="false" startupTimeLimit="3600"/>
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNet.HttpOverrides;
|
using Microsoft.AspNet.HttpOverrides;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Builder
|
namespace Microsoft.AspNet.Builder
|
||||||
|
|
@ -14,7 +15,11 @@ namespace Microsoft.AspNet.Builder
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.Use(next => new HttpMethodOverrideMiddleware(next).Invoke);
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
return builder.Use(next => new HttpMethodOverrideMiddleware(next, new HttpMethodOverrideOptions()).Invoke);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -23,9 +28,19 @@ namespace Microsoft.AspNet.Builder
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <param name="formFieldInput">Denotes the element that contains the name of the resulting method type.</param>
|
/// <param name="formFieldInput">Denotes the element that contains the name of the resulting method type.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, string formFieldInput)
|
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, Action<HttpMethodOverrideOptions> configureOptions)
|
||||||
{
|
{
|
||||||
return builder.Use(next => new HttpMethodOverrideMiddleware(next, formFieldInput).Invoke);
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
if (configureOptions == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configureOptions));
|
||||||
|
}
|
||||||
|
var options = new HttpMethodOverrideOptions();
|
||||||
|
configureOptions(options);
|
||||||
|
return builder.Use(next => new HttpMethodOverrideMiddleware(next, options).Invoke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.HttpOverrides
|
namespace Microsoft.AspNet.HttpOverrides
|
||||||
|
|
@ -12,24 +11,32 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
{
|
{
|
||||||
private const string xHttpMethodOverride = "X-Http-Method-Override";
|
private const string xHttpMethodOverride = "X-Http-Method-Override";
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly string _formFieldName;
|
private readonly HttpMethodOverrideOptions _options;
|
||||||
|
|
||||||
public HttpMethodOverrideMiddleware(RequestDelegate next, string formFieldName = null)
|
public HttpMethodOverrideMiddleware(RequestDelegate next, HttpMethodOverrideOptions options)
|
||||||
{
|
{
|
||||||
|
if (next == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(next));
|
||||||
|
}
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
}
|
||||||
_next = next;
|
_next = next;
|
||||||
_formFieldName = formFieldName;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Invoke(HttpContext context)
|
public async Task Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
if (string.Equals(context.Request.Method,"POST", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(context.Request.Method,"POST", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (_formFieldName != null)
|
if (_options.FormFieldName != null)
|
||||||
{
|
{
|
||||||
if (context.Request.HasFormContentType)
|
if (context.Request.HasFormContentType)
|
||||||
{
|
{
|
||||||
var form = await context.Request.ReadFormAsync();
|
var form = await context.Request.ReadFormAsync();
|
||||||
var methodType = form[_formFieldName];
|
var methodType = form[_options.FormFieldName];
|
||||||
if (!string.IsNullOrEmpty(methodType))
|
if (!string.IsNullOrEmpty(methodType))
|
||||||
{
|
{
|
||||||
context.Request.Method = methodType;
|
context.Request.Method = methodType;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.HttpOverrides
|
||||||
|
{
|
||||||
|
public class HttpMethodOverrideOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Denotes the form element that contains the name of the resulting method type.
|
||||||
|
/// If not set the X-Http-Method-Override header will be used.
|
||||||
|
/// </summary>
|
||||||
|
public string FormFieldName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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.AspNet.HttpOverrides
|
||||||
|
{
|
||||||
|
public static class IPEndPointParser
|
||||||
|
{
|
||||||
|
public static bool TryParse(string addressWithPort, out IPEndPoint endpoint)
|
||||||
|
{
|
||||||
|
string addressPart = null;
|
||||||
|
string portPart = null;
|
||||||
|
IPAddress address;
|
||||||
|
endpoint = null;
|
||||||
|
|
||||||
|
var lastColonIndex = addressWithPort.LastIndexOf(':');
|
||||||
|
if (lastColonIndex > 0)
|
||||||
|
{
|
||||||
|
// IPv4 with port or IPv6
|
||||||
|
var closingIndex = addressWithPort.LastIndexOf(']');
|
||||||
|
if (closingIndex > 0)
|
||||||
|
{
|
||||||
|
// IPv6 with brackets
|
||||||
|
addressPart = addressWithPort.Substring(1, closingIndex - 1);
|
||||||
|
if (closingIndex < lastColonIndex)
|
||||||
|
{
|
||||||
|
// IPv6 with port [::1]:80
|
||||||
|
portPart = addressWithPort.Substring(lastColonIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// IPv6 without port or IPv4
|
||||||
|
var firstColonIndex = addressWithPort.IndexOf(':');
|
||||||
|
if (firstColonIndex != lastColonIndex)
|
||||||
|
{
|
||||||
|
// IPv6 ::1
|
||||||
|
addressPart = addressWithPort;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// IPv4 with port 127.0.0.1:123
|
||||||
|
addressPart = addressWithPort.Substring(0, firstColonIndex);
|
||||||
|
portPart = addressWithPort.Substring(firstColonIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// IPv4 without port
|
||||||
|
addressPart = addressWithPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IPAddress.TryParse(addressPart, out address))
|
||||||
|
{
|
||||||
|
if (portPart != null)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
if (int.TryParse(portPart, out port))
|
||||||
|
{
|
||||||
|
endpoint = new IPEndPoint(address, port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
endpoint = new IPEndPoint(address, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
using Microsoft.AspNet.HttpOverrides;
|
using Microsoft.AspNet.HttpOverrides;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Builder
|
namespace Microsoft.AspNet.Builder
|
||||||
|
|
@ -13,8 +14,18 @@ namespace Microsoft.AspNet.Builder
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <param name="options">Enables the different override options.</param>
|
/// <param name="options">Enables the different override options.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseOverrideHeaders(this IApplicationBuilder builder, OverrideHeaderMiddlewareOptions options)
|
public static IApplicationBuilder UseOverrideHeaders(this IApplicationBuilder builder, Action<OverrideHeaderOptions> configureOptions)
|
||||||
{
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
if (configureOptions == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(configureOptions));
|
||||||
|
}
|
||||||
|
var options = new OverrideHeaderOptions();
|
||||||
|
configureOptions(options);
|
||||||
return builder.Use(next => new OverrideHeaderMiddleware(next, options).Invoke);
|
return builder.Use(next => new OverrideHeaderMiddleware(next, options).Invoke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Builder;
|
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.HttpOverrides
|
namespace Microsoft.AspNet.HttpOverrides
|
||||||
|
|
@ -14,19 +13,18 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
private const string XForwardedForHeaderName = "X-Forwarded-For";
|
private const string XForwardedForHeaderName = "X-Forwarded-For";
|
||||||
private const string XForwardedHostHeaderName = "X-Forwarded-Host";
|
private const string XForwardedHostHeaderName = "X-Forwarded-Host";
|
||||||
private const string XForwardedProtoHeaderName = "X-Forwarded-Proto";
|
private const string XForwardedProtoHeaderName = "X-Forwarded-Proto";
|
||||||
private const string XOriginalIPName = "X-Original-IP";
|
private const string XOriginalForName = "X-Original-For";
|
||||||
private const string XOriginalHostName = "X-Original-Host";
|
private const string XOriginalHostName = "X-Original-Host";
|
||||||
private const string XOriginalProtoName = "X-Original-Proto";
|
private const string XOriginalProtoName = "X-Original-Proto";
|
||||||
private readonly OverrideHeaderMiddlewareOptions _options;
|
private readonly OverrideHeaderOptions _options;
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
|
|
||||||
public OverrideHeaderMiddleware(RequestDelegate next, OverrideHeaderMiddlewareOptions options)
|
public OverrideHeaderMiddleware(RequestDelegate next, OverrideHeaderOptions options)
|
||||||
{
|
{
|
||||||
if (next == null)
|
if (next == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(next));
|
throw new ArgumentNullException(nameof(next));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options == null)
|
if (options == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(options));
|
throw new ArgumentNullException(nameof(options));
|
||||||
|
|
@ -37,25 +35,42 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Invoke(HttpContext context)
|
public Task Invoke(HttpContext context)
|
||||||
|
{
|
||||||
|
UpdateRemoteIp(context);
|
||||||
|
|
||||||
|
UpdateHost(context);
|
||||||
|
|
||||||
|
UpdateScheme(context);
|
||||||
|
|
||||||
|
return _next(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateRemoteIp(HttpContext context)
|
||||||
{
|
{
|
||||||
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedFor) != 0)
|
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedFor) != 0)
|
||||||
{
|
{
|
||||||
var xForwardedForHeaderValue = context.Request.Headers.GetCommaSeparatedValues(XForwardedForHeaderName);
|
var xForwardedForHeaderValue = context.Request.Headers.GetCommaSeparatedValues(XForwardedForHeaderName);
|
||||||
if (xForwardedForHeaderValue != null && xForwardedForHeaderValue.Length > 0)
|
if (xForwardedForHeaderValue != null && xForwardedForHeaderValue.Length > 0)
|
||||||
{
|
{
|
||||||
IPAddress ipFromHeader;
|
IPEndPoint endpoint;
|
||||||
if (IPAddress.TryParse(xForwardedForHeaderValue[0], out ipFromHeader))
|
if (IPEndPointParser.TryParse(xForwardedForHeaderValue[0], out endpoint))
|
||||||
{
|
{
|
||||||
var remoteIPString = context.Connection.RemoteIpAddress?.ToString();
|
var connection = context.Connection;
|
||||||
if (!string.IsNullOrEmpty(remoteIPString))
|
var remoteIP = connection.RemoteIpAddress;
|
||||||
|
if (remoteIP != null)
|
||||||
{
|
{
|
||||||
context.Request.Headers[XOriginalIPName] = remoteIPString;
|
var remoteIPString = new IPEndPoint(remoteIP, connection.RemotePort).ToString();
|
||||||
|
context.Request.Headers[XOriginalForName] = remoteIPString;
|
||||||
}
|
}
|
||||||
context.Connection.RemoteIpAddress = ipFromHeader;
|
connection.RemoteIpAddress = endpoint.Address;
|
||||||
|
connection.RemotePort = endpoint.Port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateHost(HttpContext context)
|
||||||
|
{
|
||||||
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedHost) != 0)
|
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedHost) != 0)
|
||||||
{
|
{
|
||||||
var xForwardHostHeaderValue = context.Request.Headers[XForwardedHostHeaderName];
|
var xForwardHostHeaderValue = context.Request.Headers[XForwardedHostHeaderName];
|
||||||
|
|
@ -69,7 +84,10 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
context.Request.Host = HostString.FromUriComponent(xForwardHostHeaderValue);
|
context.Request.Host = HostString.FromUriComponent(xForwardHostHeaderValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateScheme(HttpContext context)
|
||||||
|
{
|
||||||
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedProto) != 0)
|
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedProto) != 0)
|
||||||
{
|
{
|
||||||
var xForwardProtoHeaderValue = context.Request.Headers[XForwardedProtoHeaderName];
|
var xForwardProtoHeaderValue = context.Request.Headers[XForwardedProtoHeaderName];
|
||||||
|
|
@ -82,8 +100,6 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
context.Request.Scheme = xForwardProtoHeaderValue;
|
context.Request.Scheme = xForwardProtoHeaderValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _next(context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Microsoft.AspNet.HttpOverrides
|
namespace Microsoft.AspNet.HttpOverrides
|
||||||
{
|
{
|
||||||
public class OverrideHeaderMiddlewareOptions
|
public class OverrideHeaderOptions
|
||||||
{
|
{
|
||||||
public ForwardedHeaders ForwardedOptions { get; set; }
|
public ForwardedHeaders ForwardedOptions { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>f5f1d123-9c81-4a9e-8644-aa46b8e578fb</ProjectGuid>
|
<ProjectGuid>f5f1d123-9c81-4a9e-8644-aa46b8e578fb</ProjectGuid>
|
||||||
|
|
@ -12,9 +11,11 @@
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.HttpOverrides
|
||||||
|
{
|
||||||
|
public class IPEndPointParserTests
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData("127.0.0.1", "127.0.0.1", 0)]
|
||||||
|
[InlineData("127.0.0.1:1", "127.0.0.1", 1)]
|
||||||
|
[InlineData("1", "0.0.0.1", 0)]
|
||||||
|
[InlineData("1:1", "0.0.0.1", 1)]
|
||||||
|
[InlineData("::1", "::1", 0)]
|
||||||
|
[InlineData("[::1]", "::1", 0)]
|
||||||
|
[InlineData("[::1]:1", "::1", 1)]
|
||||||
|
public void ParsesCorrectly(string input, string expectedAddress, int expectedPort)
|
||||||
|
{
|
||||||
|
IPEndPoint endpoint;
|
||||||
|
var success = IPEndPointParser.TryParse(input, out endpoint);
|
||||||
|
Assert.True(success);
|
||||||
|
Assert.Equal(expectedAddress, endpoint.Address.ToString());
|
||||||
|
Assert.Equal(expectedPort, endpoint.Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
[InlineData(null)]
|
||||||
|
[InlineData("[::1]:")]
|
||||||
|
[InlineData("[::1:")]
|
||||||
|
[InlineData("::1:")]
|
||||||
|
[InlineData("127:")]
|
||||||
|
[InlineData("127.0.0.1:")]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData("[]")]
|
||||||
|
[InlineData("]")]
|
||||||
|
[InlineData("]:1")]
|
||||||
|
public void ShouldNotParse(string input)
|
||||||
|
{
|
||||||
|
IPEndPoint endpoint;
|
||||||
|
var success = IPEndPointParser.TryParse(input, out endpoint);
|
||||||
|
Assert.False(success);
|
||||||
|
Assert.Equal(null, endpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,12 +15,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task XForwardedForOverrideChangesRemoteIp()
|
public async Task XForwardedForOverrideChangesRemoteIp()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
||||||
|
|
@ -39,12 +40,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task XForwardedForOverrideBadIpDoesntChangeRemoteIp()
|
public async Task XForwardedForOverrideBadIpDoesntChangeRemoteIp()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Null(context.Connection.RemoteIpAddress);
|
Assert.Null(context.Connection.RemoteIpAddress);
|
||||||
|
|
@ -63,12 +65,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task XForwardedHostOverrideChangesRequestHost()
|
public async Task XForwardedHostOverrideChangesRequestHost()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.XForwardedHost;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.XForwardedHost;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Equal("testhost", context.Request.Host.ToString());
|
Assert.Equal("testhost", context.Request.Host.ToString());
|
||||||
|
|
@ -87,12 +90,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task XForwardedProtoOverrideChangesRequestProtocol()
|
public async Task XForwardedProtoOverrideChangesRequestProtocol()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.XForwardedProto;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.XForwardedProto;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Equal("TestProtocol", context.Request.Scheme);
|
Assert.Equal("TestProtocol", context.Request.Scheme);
|
||||||
|
|
@ -110,7 +114,7 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AllForwardsDisabledByDefault()
|
public void AllForwardsDisabledByDefault()
|
||||||
{
|
{
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
var options = new OverrideHeaderOptions();
|
||||||
Assert.True(options.ForwardedOptions == 0);
|
Assert.True(options.ForwardedOptions == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,12 +122,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task AllForwardsEnabledChangeRequestRemoteIpHostandProtocol()
|
public async Task AllForwardsEnabledChangeRequestRemoteIpHostandProtocol()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.All;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.All;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
||||||
|
|
@ -146,12 +151,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task AllOptionsDisabledRequestDoesntChange()
|
public async Task AllOptionsDisabledRequestDoesntChange()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = ForwardedHeaders.None;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.None;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Null(context.Connection.RemoteIpAddress);
|
Assert.Null(context.Connection.RemoteIpAddress);
|
||||||
|
|
@ -174,13 +180,13 @@ namespace Microsoft.AspNet.HttpOverrides
|
||||||
public async Task PartiallyEnabledForwardsPartiallyChangesRequest()
|
public async Task PartiallyEnabledForwardsPartiallyChangesRequest()
|
||||||
{
|
{
|
||||||
var assertsExecuted = false;
|
var assertsExecuted = false;
|
||||||
var XForwardedForAndProto = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
|
||||||
var options = new OverrideHeaderMiddlewareOptions();
|
|
||||||
options.ForwardedOptions = XForwardedForAndProto;
|
|
||||||
|
|
||||||
var server = TestServer.Create(app =>
|
var server = TestServer.Create(app =>
|
||||||
{
|
{
|
||||||
app.UseOverrideHeaders(options);
|
app.UseOverrideHeaders(options =>
|
||||||
|
{
|
||||||
|
options.ForwardedOptions = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||||
|
});
|
||||||
app.Run(context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue