Added a middleware to handle header overrides. Initial check in.

This commit is contained in:
Mikael Mengistu 2015-06-26 10:33:06 -07:00
parent 22ed0f5416
commit 09f492e4a6
22 changed files with 767 additions and 0 deletions

50
.gitattributes vendored Normal file
View File

@ -0,0 +1,50 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.resx text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto
*.vbproj text=auto
*.fsproj text=auto
*.dbproj text=auto
*.sln text=auto eol=crlf

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
[Oo]bj/
[Bb]in/
TestResults/
.nuget/
*.sln.ide/
_ReSharper.*/
packages/
artifacts/
PublishProfiles/
*.user
*.suo
*.cache
*.docstates
_ReSharper.*
nuget.exe
project.lock.json
*net45.csproj
*net451.csproj
*k10.csproj
*.psess
*.vsp
*.pidb
*.userprefs
*DS_Store
*.ncrunchsolution
*.*sdf
*.ipch
.vs/

4
.travis.yml Normal file
View File

@ -0,0 +1,4 @@
language: csharp
sudo: false
script:
- ./build.sh --quiet verify

41
BasicMiddleware.sln Normal file
View File

@ -0,0 +1,41 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23018.0
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}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5076D28-FA7E-4606-9410-FEDD0D603527}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8437B0F3-3894-4828-A945-A9187F37631D}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.HttpOverrides.Tests", "test\Microsoft.AspNet.HttpOverrides.Tests\Microsoft.AspNet.HttpOverrides.Tests.xproj", "{D6341B92-3416-4F11-8DF4-CB274296175F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{99B72A07-32D6-434D-B44D-D064E3C13E08}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{517308C3-B477-4B01-B461-CAB9C10B6928}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{517308C3-B477-4B01-B461-CAB9C10B6928}.Debug|Any CPU.Build.0 = Debug|Any CPU
{517308C3-B477-4B01-B461-CAB9C10B6928}.Release|Any CPU.ActiveCfg = Release|Any CPU
{517308C3-B477-4B01-B461-CAB9C10B6928}.Release|Any CPU.Build.0 = Release|Any CPU
{D6341B92-3416-4F11-8DF4-CB274296175F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6341B92-3416-4F11-8DF4-CB274296175F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6341B92-3416-4F11-8DF4-CB274296175F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6341B92-3416-4F11-8DF4-CB274296175F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{517308C3-B477-4B01-B461-CAB9C10B6928} = {A5076D28-FA7E-4606-9410-FEDD0D603527}
{D6341B92-3416-4F11-8DF4-CB274296175F} = {8437B0F3-3894-4828-A945-A9187F37631D}
EndGlobalSection
EndGlobal

7
NuGet.Config Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetvnext/api/v2" />
<add key="NuGet" value="https://nuget.org/api/v2/" />
</packageSources>
</configuration>

7
appveyor.yml Normal file
View File

@ -0,0 +1,7 @@
init:
- git config --global core.autocrlf true
build_script:
- build.cmd --quiet verify
clone_depth: 1
test: off
deploy: off

28
build.cmd Normal file
View File

@ -0,0 +1,28 @@
@echo off
cd %~dp0
SETLOCAL
SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe
IF EXIST %CACHED_NUGET% goto copynuget
echo Downloading latest version of NuGet.exe...
IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'"
:copynuget
IF EXIST .nuget\nuget.exe goto restore
md .nuget
copy %CACHED_NUGET% .nuget\nuget.exe > nul
:restore
IF EXIST packages\KoreBuild goto run
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
IF "%SKIP_DNX_INSTALL%"=="1" goto run
CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86
CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86
:run
CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*

39
build.sh Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
if test `uname` = Darwin; then
cachedir=~/Library/Caches/KBuild
else
if [ -z $XDG_DATA_HOME ]; then
cachedir=$HOME/.local/share
else
cachedir=$XDG_DATA_HOME;
fi
fi
mkdir -p $cachedir
url=https://www.nuget.org/nuget.exe
if test ! -f $cachedir/nuget.exe; then
wget -O $cachedir/nuget.exe $url 2>/dev/null || curl -o $cachedir/nuget.exe --location $url /dev/null
fi
if test ! -e .nuget; then
mkdir .nuget
cp $cachedir/nuget.exe .nuget/nuget.exe
fi
if test ! -d packages/KoreBuild; then
mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
mono .nuget/nuget.exe install Sake -version 0.2 -o packages -ExcludeVersion
fi
if ! type dnvm > /dev/null 2>&1; then
source packages/KoreBuild/build/dnvm.sh
fi
if ! type dnx > /dev/null 2>&1; then
dnvm upgrade
fi
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"

3
global.json Normal file
View File

@ -0,0 +1,3 @@
{
"projects": [ "src" ]
}

8
makefile.shade Normal file
View File

@ -0,0 +1,8 @@
use namespace="System.Net"
var VERSION='0.1'
var FULL_VERSION='0.1'
var AUTHORS='Microsoft Open Technologies, Inc.'
use-standard-lifecycle
k-standard-goals

View File

@ -0,0 +1,17 @@
// 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;
namespace Microsoft.AspNet.HttpOverrides
{
[Flags]
public enum ForwardedHeaders
{
None = 0,
XForwardedFor = 1 << 0,
XForwardedHost = 1 << 1,
XForwardedProto = 1 << 2,
All = XForwardedFor | XForwardedHost | XForwardedProto
}
}

View File

@ -0,0 +1,31 @@
// 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.AspNet.HttpOverrides;
namespace Microsoft.AspNet.Builder
{
public static class HttpMethodOverrideExtensions
{
/// <summary>
/// Allows incoming POST request to override method type with type specified in header.
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder)
{
return builder.Use(next => new HttpMethodOverrideMiddleware(next).Invoke);
}
/// <summary>
/// Allows incoming POST request to override method type with type specified in form.
/// </summary>
/// <param name="builder"></param>
/// <param name="formFieldInput">Denotes the element that contains the name of the resulting method type.</param>
/// <returns></returns>
public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, string formFieldInput)
{
return builder.Use(next => new HttpMethodOverrideMiddleware(next, formFieldInput).Invoke);
}
}
}

View File

@ -0,0 +1,51 @@
// 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;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.HttpOverrides
{
public class HttpMethodOverrideMiddleware
{
private const string xHttpMethodOverride = "X-Http-Method-Override";
private readonly RequestDelegate _next;
private readonly string _formFieldName;
public HttpMethodOverrideMiddleware(RequestDelegate next, string formFieldName = null)
{
_next = next;
_formFieldName = formFieldName;
}
public async Task Invoke(HttpContext context)
{
if (string.Equals(context.Request.Method,"POST", StringComparison.OrdinalIgnoreCase))
{
if (_formFieldName != null)
{
if (context.Request.HasFormContentType)
{
var form = await context.Request.ReadFormAsync();
var methodType = form[_formFieldName];
if (!string.IsNullOrEmpty(methodType))
{
context.Request.Method = methodType;
}
}
}
else
{
var xHttpMethodOverrideValue = context.Request.Headers.Get(xHttpMethodOverride);
if (!string.IsNullOrEmpty(xHttpMethodOverrideValue))
{
context.Request.Method = xHttpMethodOverrideValue;
}
}
}
await _next(context);
}
}
}

View File

@ -0,0 +1,17 @@
<?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>517308c3-b477-4b01-b461-cab9c10b6928</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,21 @@
// 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.AspNet.HttpOverrides;
namespace Microsoft.AspNet.Builder
{
public static class OverrideHeaderExtensions
{
/// <summary>
/// Forwards proxied headers onto current request
/// </summary>
/// <param name="builder"></param>
/// <param name="options">Enables the different override options.</param>
/// <returns></returns>
public static IApplicationBuilder UseOverrideHeaders(this IApplicationBuilder builder, OverrideHeaderMiddlewareOptions options)
{
return builder.Use(next => new OverrideHeaderMiddleware(next, options).Invoke);
}
}
}

View File

@ -0,0 +1,68 @@
// 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;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.HttpOverrides
{
public class OverrideHeaderMiddleware
{
private const string XForwardedForHeaderName = "X-Forwarded-For";
private const string XForwardedHostHeaderName = "X-Forwarded-Host";
private const string XForwardedProtoHeaderName = "X-Forwarded-Proto";
private readonly OverrideHeaderMiddlewareOptions _options;
private readonly RequestDelegate _next;
public OverrideHeaderMiddleware([NotNull] RequestDelegate next, [NotNull] OverrideHeaderMiddlewareOptions options)
{
_options = options;
_next = next;
}
public Task Invoke(HttpContext context)
{
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedFor) != 0)
{
var xForwardedForHeaderValue = context.Request.Headers.GetCommaSeparatedValues(XForwardedForHeaderName);
if (xForwardedForHeaderValue != null && xForwardedForHeaderValue.Count > 0)
{
IPAddress originalIPAddress;
if (IPAddress.TryParse(xForwardedForHeaderValue[0], out originalIPAddress))
{
if (context.Connection.RemoteIpAddress != null)
{
var ipList = context.Request.Headers.Get(XForwardedForHeaderName);
context.Request.Headers.Set(XForwardedForHeaderName, (ipList + "," + context.Connection.RemoteIpAddress.ToString()));
}
context.Connection.RemoteIpAddress = originalIPAddress;
}
}
}
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedHost) != 0)
{
var xForwardHostHeaderValue = context.Request.Headers.Get(XForwardedHostHeaderName);
if (!string.IsNullOrEmpty(xForwardHostHeaderValue))
{
context.Request.Host = HostString.FromUriComponent(xForwardHostHeaderValue);
}
}
if ((_options.ForwardedOptions & ForwardedHeaders.XForwardedProto) != 0)
{
var xForwardProtoHeaderValue = context.Request.Headers.Get(XForwardedProtoHeaderName);
if (!string.IsNullOrEmpty(xForwardProtoHeaderValue))
{
context.Request.Scheme = xForwardProtoHeaderValue;
}
}
return _next(context);
}
}
}

View File

@ -0,0 +1,10 @@
// 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 OverrideHeaderMiddlewareOptions
{
public ForwardedHeaders ForwardedOptions { get; set; }
}
}

View File

@ -0,0 +1,19 @@
{
"version": "1.0.0-*",
"description": "XForward and Method override middlewares for ASP.NET",
"dependencies": {
"Microsoft.CSharp": "4.0.0-*",
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
"Microsoft.Framework.NotNullAttribute.Sources": { "version": "1.0.0-*", "type": "build" }
},
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Collections": "4.0.10-*",
"System.Linq": "4.0.0-*",
"System.Threading": "4.0.10-*"
}
}
}
}

View File

@ -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.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Xunit;
namespace Microsoft.AspNet.HttpOverrides
{
public class HttpMethodOverrideMiddlewareTest
{
[Fact]
public async Task XHttpMethodOverrideHeaderAvaiableChangesRequestMethod()
{
var assertsExecuted = false;
var server = TestServer.Create(app =>
{
app.UseHttpMethodOverride();
app.Run(context =>
{
assertsExecuted = true;
Assert.Equal("DELETE", context.Request.Method);
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Post, "");
req.Headers.Add("X-Http-Method-Override", "DELETE");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task XHttpMethodOverrideHeaderUnavaiableDoesntChangeRequestMethod()
{
var assertsExecuted = false;
var server = TestServer.Create(app =>
{
app.UseHttpMethodOverride();
app.Run(context =>
{
Assert.Equal("POST",context.Request.Method);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Post, "");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task XHttpMethodOverrideFromGetRequestDoesntChangeMethodType()
{
var assertsExecuted = false;
var server = TestServer.Create(app =>
{
app.UseHttpMethodOverride();
app.Run(context =>
{
Assert.Equal("GET", context.Request.Method);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
}
}

View File

@ -0,0 +1,20 @@
<?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>d6341b92-3416-4f11-8df4-cb274296175f</ProjectGuid>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,202 @@
// 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.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Xunit;
namespace Microsoft.AspNet.HttpOverrides
{
public class OverrideMiddlewareHeaderTests
{
[Fact]
public async Task XForwardedForOverrideChangesRemoteIp()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-For", "11.111.111.11");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task XForwardedForOverrideBadIpDoesntChangeRemoteIp()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.XForwardedFor;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Null(context.Connection.RemoteIpAddress);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-For", "BAD-IP");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task XForwardedHostOverrideChangesRequestHost()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.XForwardedHost;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Equal("testHost", context.Request.Host.ToString());
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-Host", "testHost");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task XForwardedProtoOverrideChangesRequestProtocol()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.XForwardedProto;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Equal("TestProtocol", context.Request.Scheme);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-Proto", "TestProtocol");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public void AllForwardsDisabledByDefault()
{
var options = new OverrideHeaderMiddlewareOptions();
Assert.True(options.ForwardedOptions == 0);
}
[Fact]
public async Task AllForwardsEnabledChangeRequestRemoteIpHostandProtocol()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.All;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
Assert.Equal("testHost", context.Request.Host.ToString());
Assert.Equal("Protocol", context.Request.Scheme);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-For", "11.111.111.11");
req.Headers.Add("X-Forwarded-Host", "testHost");
req.Headers.Add("X-Forwarded-Proto", "Protocol");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task AllOptionsDisabledRequestDoesntChange()
{
var assertsExecuted = false;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = ForwardedHeaders.None;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Null(context.Connection.RemoteIpAddress);
Assert.Equal("localhost", context.Request.Host.ToString());
Assert.Equal("http", context.Request.Scheme);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-For", "11.111.111.11");
req.Headers.Add("X-Forwarded-Host", "otherhost");
req.Headers.Add("X-Forwarded-Proto", "Protocol");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Fact]
public async Task PartiallyEnabledForwardsPartiallyChangesRequest()
{
var assertsExecuted = false;
var XForwardedForAndProto = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
var options = new OverrideHeaderMiddlewareOptions();
options.ForwardedOptions = XForwardedForAndProto;
var server = TestServer.Create(app =>
{
app.UseOverrideHeaders(options);
app.Run(context =>
{
Assert.Equal("11.111.111.11", context.Connection.RemoteIpAddress.ToString());
Assert.Equal("localhost", context.Request.Host.ToString());
Assert.Equal("Protocol", context.Request.Scheme);
assertsExecuted = true;
return Task.FromResult(0);
});
});
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.Add("X-Forwarded-For", "11.111.111.11");
req.Headers.Add("X-Forwarded-Proto", "Protocol");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
}
}

View File

@ -0,0 +1,23 @@
{
"version": "1.0.0-*",
"dependencies": {
"Microsoft.AspNet.HttpOverrides": "1.0.0-*",
"Microsoft.AspNet.TestHost": "1.0.0-*",
"Microsoft.Framework.Logging.Testing": "1.0.0-*",
"xunit.runner.aspnet": "2.0.0-aspnet-*"
},
"commands": {
"test": "xunit.runner.aspnet"
},
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Collections": "4.0.10-*",
"System.Linq": "4.0.0-*",
"System.Threading": "4.0.10-*"
}
}
}
}