Make https redirect no-op if no port is available #318
This commit is contained in:
parent
0c31fcdf30
commit
0a876cece7
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="$(MicrosoftAspNetCoreServerKestrelHttpsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:31895/"
|
||||
"applicationUrl": "http://localhost:5000/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Hosting;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace HttpsSample
|
||||
{
|
||||
|
|
@ -62,6 +63,11 @@ namespace HttpsSample
|
|||
});
|
||||
})
|
||||
.UseContentRoot(Directory.GetCurrentDirectory()) // for the cert file
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
factory.SetMinimumLevel(LogLevel.Debug);
|
||||
factory.AddConsole();
|
||||
})
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ using Microsoft.AspNetCore.Hosting.Server.Features;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
using Microsoft.AspNetCore.Http.Internal;
|
||||
using Microsoft.AspNetCore.HttpsPolicy.Internal;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
|
|
@ -16,11 +18,13 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
public class HttpsRedirectionMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private bool _portEvaluated = false;
|
||||
private int? _httpsPort;
|
||||
private readonly int _statusCode;
|
||||
|
||||
private readonly IServerAddressesFeature _serverAddressesFeature;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the HttpsRedirectionMiddleware
|
||||
|
|
@ -28,7 +32,8 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
/// <param name="next"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="config"></param>
|
||||
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config)
|
||||
/// <param name="loggerFactory"></param>
|
||||
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory)
|
||||
|
||||
{
|
||||
_next = next ?? throw new ArgumentNullException(nameof(next));
|
||||
|
|
@ -40,7 +45,9 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
}
|
||||
var httpsRedirectionOptions = options.Value;
|
||||
_httpsPort = httpsRedirectionOptions.HttpsPort;
|
||||
_portEvaluated = _httpsPort.HasValue;
|
||||
_statusCode = httpsRedirectionOptions.RedirectStatusCode;
|
||||
_logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -49,9 +56,11 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
/// <param name="next"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="loggerFactory"></param>
|
||||
/// <param name="serverAddressesFeature">The</param>
|
||||
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, IServerAddressesFeature serverAddressesFeature)
|
||||
: this(next, options, config)
|
||||
public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory,
|
||||
IServerAddressesFeature serverAddressesFeature)
|
||||
: this(next, options, config, loggerFactory)
|
||||
{
|
||||
_serverAddressesFeature = serverAddressesFeature ?? throw new ArgumentNullException(nameof(serverAddressesFeature));
|
||||
}
|
||||
|
|
@ -63,20 +72,15 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
/// <returns></returns>
|
||||
public Task Invoke(HttpContext context)
|
||||
{
|
||||
if (context.Request.IsHttps)
|
||||
if (context.Request.IsHttps || !TryGetHttpsPort(out var port))
|
||||
{
|
||||
return _next(context);
|
||||
}
|
||||
|
||||
if (!_httpsPort.HasValue)
|
||||
{
|
||||
CheckForHttpsPorts();
|
||||
}
|
||||
|
||||
var host = context.Request.Host;
|
||||
if (_httpsPort != 443)
|
||||
if (port != 443)
|
||||
{
|
||||
host = new HostString(host.Host, _httpsPort.Value);
|
||||
host = new HostString(host.Host, port);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -94,28 +98,41 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
context.Response.StatusCode = _statusCode;
|
||||
context.Response.Headers[HeaderNames.Location] = redirectUrl;
|
||||
|
||||
_logger.RedirectingToHttps(redirectUrl);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void CheckForHttpsPorts()
|
||||
private bool TryGetHttpsPort(out int port)
|
||||
{
|
||||
// The IServerAddressesFeature will not be ready until the middleware is Invoked,
|
||||
// Order for finding the HTTPS port:
|
||||
// 1. Set in the HttpsRedirectionOptions
|
||||
// 2. HTTPS_PORT environment variable
|
||||
// 3. IServerAddressesFeature
|
||||
// 4. 443 (or not set)
|
||||
// 4. Fail if not set
|
||||
|
||||
port = -1;
|
||||
|
||||
if (_portEvaluated)
|
||||
{
|
||||
port = _httpsPort ?? port;
|
||||
return _httpsPort.HasValue;
|
||||
}
|
||||
_portEvaluated = true;
|
||||
|
||||
_httpsPort = _config.GetValue<int?>("HTTPS_PORT");
|
||||
if (_httpsPort.HasValue)
|
||||
{
|
||||
return;
|
||||
port = _httpsPort.Value;
|
||||
_logger.PortLoadedFromConfig(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_serverAddressesFeature == null)
|
||||
{
|
||||
_httpsPort = 443;
|
||||
return;
|
||||
_logger.FailedToDeterminePort();
|
||||
return false;
|
||||
}
|
||||
|
||||
int? httpsPort = null;
|
||||
|
|
@ -127,8 +144,8 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
// If we find multiple different https ports specified, throw
|
||||
if (httpsPort.HasValue && httpsPort != bindingAddress.Port)
|
||||
{
|
||||
throw new ArgumentException("Cannot determine the https port from IServerAddressesFeature, multiple values were found. " +
|
||||
"Please set the desired port explicitly on HttpsRedirectionOptions.HttpsPort.");
|
||||
_logger.FailedMultiplePorts();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -136,7 +153,17 @@ namespace Microsoft.AspNetCore.HttpsPolicy
|
|||
}
|
||||
}
|
||||
}
|
||||
_httpsPort = httpsPort ?? 443;
|
||||
|
||||
if (httpsPort.HasValue)
|
||||
{
|
||||
_httpsPort = httpsPort;
|
||||
port = _httpsPort.Value;
|
||||
_logger.PortFromServer(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.FailedToDeterminePort();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// 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 Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.HttpsPolicy.Internal
|
||||
{
|
||||
internal static class HttpsLoggingExtensions
|
||||
{
|
||||
private static readonly Action<ILogger, string, Exception> _redirectingToHttps;
|
||||
private static readonly Action<ILogger, int, Exception> _portLoadedFromConfig;
|
||||
private static readonly Action<ILogger, Exception> _failedToDeterminePort;
|
||||
private static readonly Action<ILogger, Exception> _failedMultiplePorts;
|
||||
private static readonly Action<ILogger, int, Exception> _portFromServer;
|
||||
|
||||
static HttpsLoggingExtensions()
|
||||
{
|
||||
_redirectingToHttps = LoggerMessage.Define<string>(LogLevel.Debug, 1, "Redirecting to '{redirect}'.");
|
||||
_portLoadedFromConfig = LoggerMessage.Define<int>(LogLevel.Debug, 2, "Https port '{port}' loaded from configuration.");
|
||||
_failedToDeterminePort = LoggerMessage.Define(LogLevel.Warning, 3, "Failed to determine the https port for redirect.");
|
||||
_failedMultiplePorts = LoggerMessage.Define(LogLevel.Warning, 4,
|
||||
"Cannot determine the https port from IServerAddressesFeature, multiple values were found. " +
|
||||
"Please set the desired port explicitly on HttpsRedirectionOptions.HttpsPort.");
|
||||
_portFromServer = LoggerMessage.Define<int>(LogLevel.Debug, 5, "Https port '{httpsPort}' discovered from server endpoints.");
|
||||
}
|
||||
|
||||
public static void RedirectingToHttps(this ILogger logger, string redirect)
|
||||
{
|
||||
_redirectingToHttps(logger, redirect, null);
|
||||
}
|
||||
|
||||
public static void PortLoadedFromConfig(this ILogger logger, int port)
|
||||
{
|
||||
_portLoadedFromConfig(logger, port, null);
|
||||
}
|
||||
|
||||
public static void FailedToDeterminePort(this ILogger logger)
|
||||
{
|
||||
_failedToDeterminePort(logger, null);
|
||||
}
|
||||
|
||||
public static void FailedMultiplePorts(this ILogger logger)
|
||||
{
|
||||
_failedMultiplePorts(logger, null);
|
||||
}
|
||||
|
||||
public static void PortFromServer(this ILogger logger, int port)
|
||||
{
|
||||
_portFromServer(logger, port, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,12 +21,12 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
public class HttpsPolicyTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(302, null, 2592000, false, false, "max-age=2592000", "https://localhost/")]
|
||||
[InlineData(302, 443, 2592000, false, false, "max-age=2592000", "https://localhost/")]
|
||||
[InlineData(301, 5050, 2592000, false, false, "max-age=2592000", "https://localhost:5050/")]
|
||||
[InlineData(301, 443, 2592000, false, false, "max-age=2592000", "https://localhost/")]
|
||||
[InlineData(301, 443, 2592000, true, false, "max-age=2592000; includeSubDomains", "https://localhost/")]
|
||||
[InlineData(301, 443, 2592000, false, true, "max-age=2592000; preload", "https://localhost/")]
|
||||
[InlineData(301, null, 2592000, true, true, "max-age=2592000; includeSubDomains; preload", "https://localhost/")]
|
||||
[InlineData(301, 443, 2592000, true, true, "max-age=2592000; includeSubDomains; preload", "https://localhost/")]
|
||||
[InlineData(302, 5050, 2592000, true, true, "max-age=2592000; includeSubDomains; preload", "https://localhost:5050/")]
|
||||
public async Task SetsBothHstsAndHttpsRedirection_RedirectOnFirstRequest_HstsOnSecondRequest(int statusCode, int? tlsPort, int maxAge, bool includeSubDomains, bool preload, string expectedHstsHeader, string expectedUrl)
|
||||
{
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
|
||||
client = server.CreateClient();
|
||||
client.BaseAddress = new Uri(response.Headers.Location.ToString());
|
||||
request = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
request = new HttpRequestMessage(HttpMethod.Get, expectedUrl);
|
||||
response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal(expectedHstsHeader, response.Headers.GetValues(HeaderNames.StrictTransportSecurity).FirstOrDefault());
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -12,6 +13,8 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
||||
|
|
@ -19,9 +22,17 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
public class HttpsRedirectionMiddlewareTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task SetOptions_DefaultsSetCorrectly()
|
||||
public async Task SetOptions_NotEnabledByDefault()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
|
|
@ -38,23 +49,32 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.RedirectKeepVerb, response.StatusCode);
|
||||
Assert.Equal("https://localhost/", response.Headers.Location.ToString());
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.Single();
|
||||
Assert.Equal(LogLevel.Warning, message.LogLevel);
|
||||
Assert.Equal("Failed to determine the https port for redirect.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(301, null, "https://localhost/")]
|
||||
[InlineData(302, null, "https://localhost/")]
|
||||
[InlineData(307, null, "https://localhost/")]
|
||||
[InlineData(308, null, "https://localhost/")]
|
||||
[InlineData(302, 5001, "https://localhost:5001/")]
|
||||
[InlineData(307, 1, "https://localhost:1/")]
|
||||
[InlineData(308, 3449, "https://localhost:3449/")]
|
||||
[InlineData(301, 5050, "https://localhost:5050/")]
|
||||
[InlineData(301, 443, "https://localhost/")]
|
||||
public async Task SetOptions_SetStatusCodeHttpsPort(int statusCode, int? httpsPort, string expected)
|
||||
{
|
||||
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
services.Configure<HttpsRedirectionOptions>(options =>
|
||||
{
|
||||
options.RedirectStatusCode = statusCode;
|
||||
|
|
@ -79,20 +99,31 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
|
||||
Assert.Equal(statusCode, (int)response.StatusCode);
|
||||
Assert.Equal(expected, response.Headers.Location.ToString());
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.Single();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal($"Redirecting to '{expected}'.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(301, null, "https://localhost/")]
|
||||
[InlineData(302, null, "https://localhost/")]
|
||||
[InlineData(307, null, "https://localhost/")]
|
||||
[InlineData(308, null, "https://localhost/")]
|
||||
[InlineData(302, 5001, "https://localhost:5001/")]
|
||||
[InlineData(307, 1, "https://localhost:1/")]
|
||||
[InlineData(308, 3449, "https://localhost:3449/")]
|
||||
[InlineData(301, 5050, "https://localhost:5050/")]
|
||||
[InlineData(301, 443, "https://localhost/")]
|
||||
public async Task SetOptionsThroughHelperMethod_SetStatusCodeAndHttpsPort(int statusCode, int? httpsPort, string expectedUrl)
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
services.AddHttpsRedirection(options =>
|
||||
{
|
||||
options.RedirectStatusCode = statusCode;
|
||||
|
|
@ -117,20 +148,26 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
|
||||
Assert.Equal(statusCode, (int)response.StatusCode);
|
||||
Assert.Equal(expectedUrl, response.Headers.Location.ToString());
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.Single();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal($"Redirecting to '{expectedUrl}'.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, "https://localhost/")]
|
||||
[InlineData(null, null, "https://localhost:4444/", "https://localhost:4444/")]
|
||||
[InlineData(null, null, "https://localhost:443/", "https://localhost/")]
|
||||
[InlineData(null, null, "http://localhost:5044/", "https://localhost/")]
|
||||
[InlineData(null, null, "https://localhost/", "https://localhost/")]
|
||||
[InlineData(null, "5000", "https://localhost:4444/", "https://localhost:5000/")]
|
||||
[InlineData(null, "443", "https://localhost:4444/", "https://localhost/")]
|
||||
[InlineData(443, "5000", "https://localhost:4444/", "https://localhost/")]
|
||||
[InlineData(4000, "5000", "https://localhost:4444/", "https://localhost:4000/")]
|
||||
[InlineData(5000, null, "https://localhost:4444/", "https://localhost:5000/")]
|
||||
public async Task SetHttpsPortEnvironmentVariableAndServerFeature_ReturnsCorrectStatusCodeOnResponse(int? optionsHttpsPort, string configHttpsPort, string serverAddressFeatureUrl, string expectedUrl)
|
||||
public async Task SetHttpsPortEnvironmentVariableAndServerFeature_ReturnsCorrectStatusCodeOnResponse(
|
||||
int? optionsHttpsPort, string configHttpsPort, string serverAddressFeatureUrl, string expectedUrl)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
|
|
@ -172,7 +209,15 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
[Fact]
|
||||
public async Task SetServerAddressesFeature_SingleHttpsAddress_Success()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
|
|
@ -194,12 +239,31 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal("https://localhost:5050/", response.Headers.Location.ToString());
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Equal(2, logMessages.Count);
|
||||
var message = logMessages.First();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal("Https port '5050' discovered from server endpoints.", message.State.ToString());
|
||||
|
||||
message = logMessages.Skip(1).First();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal("Redirecting to 'https://localhost:5050/'.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SetServerAddressesFeature_MultipleHttpsAddresses_ThrowInMiddleware()
|
||||
public async Task SetServerAddressesFeature_MultipleHttpsAddresses_LogsAndFailsToRedirect()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
|
|
@ -220,13 +284,30 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
|
||||
await Assert.ThrowsAsync<ArgumentException>(async () => await client.SendAsync(request));
|
||||
var response = await client.SendAsync(request);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.First();
|
||||
Assert.Equal(LogLevel.Warning, message.LogLevel);
|
||||
Assert.Equal("Cannot determine the https port from IServerAddressesFeature, multiple values were found. " +
|
||||
"Please set the desired port explicitly on HttpsRedirectionOptions.HttpsPort.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SetServerAddressesFeature_MultipleHttpsAddressesWithSamePort_Success()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseHttpsRedirection();
|
||||
|
|
@ -241,7 +322,7 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
var server = new TestServer(builder, featureCollection);
|
||||
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add("https://localhost:5050");
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add("https://localhost:5050");
|
||||
server.Features.Get<IServerAddressesFeature>().Addresses.Add("https://example.com:5050");
|
||||
|
||||
var client = server.CreateClient();
|
||||
|
||||
|
|
@ -250,17 +331,30 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
var response = await client.SendAsync(request);
|
||||
|
||||
Assert.Equal("https://localhost:5050/", response.Headers.Location.ToString());
|
||||
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Equal(2, logMessages.Count);
|
||||
var message = logMessages.First();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal("Https port '5050' discovered from server endpoints.", message.State.ToString());
|
||||
|
||||
message = logMessages.Skip(1).First();
|
||||
Assert.Equal(LogLevel.Debug, message.LogLevel);
|
||||
Assert.Equal("Redirecting to 'https://localhost:5050/'.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NoServerAddressFeature_DoesNotThrow_DefaultsTo443()
|
||||
public async Task NoServerAddressFeature_DoesNotThrow_DoesNotRedirect()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddHttpsRedirection(options =>
|
||||
{
|
||||
});
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -275,19 +369,27 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
var client = server.CreateClient();
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
var response = await client.SendAsync(request);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
|
||||
Assert.Equal("https://localhost/", response.Headers.Location.ToString());
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.First();
|
||||
Assert.Equal(LogLevel.Warning, message.LogLevel);
|
||||
Assert.Equal("Failed to determine the https port for redirect.", message.State.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SetNullAddressFeature_DoesNotThrow()
|
||||
{
|
||||
var sink = new TestSink(
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,
|
||||
TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);
|
||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddHttpsRedirection(options =>
|
||||
{
|
||||
});
|
||||
services.AddSingleton<ILoggerFactory>(loggerFactory);
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
|
|
@ -305,8 +407,14 @@ namespace Microsoft.AspNetCore.HttpsPolicy.Tests
|
|||
var client = server.CreateClient();
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "");
|
||||
var response = await client.SendAsync(request);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
|
||||
Assert.Equal("https://localhost/", response.Headers.Location.ToString());
|
||||
var logMessages = sink.Writes.ToList();
|
||||
|
||||
Assert.Single(logMessages);
|
||||
var message = logMessages.First();
|
||||
Assert.Equal(LogLevel.Warning, message.LogLevel);
|
||||
Assert.Equal("Failed to determine the https port for redirect.", message.State.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
||||
|
|
@ -8,4 +8,8 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.HttpsPolicy\Microsoft.AspNetCore.HttpsPolicy.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Reference in New Issue