#283 Update naming, merge options

This commit is contained in:
Chris R 2016-12-15 14:38:59 -08:00
parent 4c388e89ce
commit d7ce8d8103
32 changed files with 152 additions and 212 deletions

View File

@ -15,19 +15,19 @@ namespace HotAddSample
{
public void ConfigureServices(IServiceCollection services)
{
services.Configure<WebListenerOptions>(options =>
services.Configure<HttpSysOptions>(options =>
{
ListenerSettings = options.ListenerSettings;
ServerOptions = options;
});
}
public WebListenerSettings ListenerSettings { get; set; }
public HttpSysOptions ServerOptions { get; set; }
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
loggerfactory.AddConsole(LogLevel.Information);
var addresses = ListenerSettings.UrlPrefixes;
var addresses = ServerOptions.UrlPrefixes;
addresses.Add("http://localhost:12346/pathBase/");
app.Use(async (context, next) =>
@ -102,7 +102,7 @@ namespace HotAddSample
{
var host = new WebHostBuilder()
.UseStartup<Startup>()
.UseWebListener()
.UseHttpSys()
.Build();
host.Run();

View File

@ -16,10 +16,10 @@ namespace SelfHostServer
public void ConfigureServices(IServiceCollection services)
{
// Server options can be configured here instead of in Main.
services.Configure<WebListenerOptions>(options =>
services.Configure<HttpSysOptions>(options =>
{
options.ListenerSettings.Authentication.Schemes = AuthenticationSchemes.None;
options.ListenerSettings.Authentication.AllowAnonymous = true;
options.Authentication.Schemes = AuthenticationSchemes.None;
options.Authentication.AllowAnonymous = true;
});
}
@ -49,10 +49,10 @@ namespace SelfHostServer
{
var host = new WebHostBuilder()
.UseStartup<Startup>()
.UseWebListener(options =>
.UseHttpSys(options =>
{
options.ListenerSettings.Authentication.Schemes = AuthenticationSchemes.None;
options.ListenerSettings.Authentication.AllowAnonymous = true;
options.Authentication.Schemes = AuthenticationSchemes.None;
options.Authentication.AllowAnonymous = true;
})
.Build();

View File

@ -14,10 +14,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
internal static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(IOWaitCallback);
private TaskCompletionSource<RequestContext> _tcs;
private WebListener _server;
private HttpSysListener _server;
private NativeRequestContext _nativeRequestContext;
internal AsyncAcceptContext(WebListener server)
internal AsyncAcceptContext(HttpSysListener server)
{
_server = server;
_tcs = new TaskCompletionSource<RequestContext>();
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
}
internal WebListener Server
internal HttpSysListener Server
{
get
{
@ -58,12 +58,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
{
asyncResult.Tcs.TrySetException(new WebListenerException((int)errorCode));
asyncResult.Tcs.TrySetException(new HttpSysException((int)errorCode));
complete = true;
}
else
{
WebListener server = asyncResult.Server;
HttpSysListener server = asyncResult.Server;
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
// someother bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
asyncResult.Tcs.TrySetException(new WebListenerException((int)statusCode));
asyncResult.Tcs.TrySetException(new HttpSysException((int)statusCode));
complete = true;
}
}
@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
retry = true;
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS
&& WebListener.SkipIOCPCallbackOnSuccess)
&& HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
IOCompleted(this, statusCode, bytesTransferred);

View File

@ -9,19 +9,19 @@ using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Server.HttpSys
{
[SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")]
public class WebListenerException : Win32Exception
public class HttpSysException : Win32Exception
{
internal WebListenerException()
internal HttpSysException()
: base(Marshal.GetLastWin32Error())
{
}
internal WebListenerException(int errorCode)
internal HttpSysException(int errorCode)
: base(errorCode)
{
}
internal WebListenerException(int errorCode, string message)
internal HttpSysException(int errorCode, string message)
: base(errorCode, message)
{
}

View File

@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
/// <summary>
/// An HTTP server wrapping the Http.Sys APIs that accepts requests.
/// </summary>
public sealed class WebListener : IDisposable
public sealed class HttpSysListener : IDisposable
{
// Win8# 559317 fixed a bug in Http.sys's HttpReceiveClientCertificate method.
// Without this fix IOCP callbacks were not being called although ERROR_IO_PENDING was
@ -40,16 +40,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private object _internalLock;
public WebListener()
: this(new WebListenerSettings())
public HttpSysListener(HttpSysOptions options, ILoggerFactory loggerFactory)
{
}
public WebListener(WebListenerSettings settings)
{
if (settings == null)
if (options == null)
{
throw new ArgumentNullException(nameof(settings));
throw new ArgumentNullException(nameof(options));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
if (!HttpApi.Supported)
@ -59,7 +58,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Debug.Assert(HttpApi.ApiVersion == HttpApi.HTTP_API_VERSION.Version20, "Invalid Http api version");
Settings = settings;
Options = options;
Logger = LogHelper.CreateLogger(loggerFactory, typeof(HttpSysListener));
_state = State.Stopped;
_internalLock = new object();
@ -99,10 +100,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Disposed,
}
internal ILogger Logger
{
get { return Settings.Logger; }
}
internal ILogger Logger { get; private set; }
internal UrlGroup UrlGroup
{
@ -119,7 +117,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
get { return _disconnectListener; }
}
public WebListenerSettings Settings { get; }
public HttpSysOptions Options { get; }
public bool IsListening
{
@ -148,18 +146,18 @@ namespace Microsoft.AspNetCore.Server.HttpSys
return;
}
Settings.Authentication.SetUrlGroupSecurity(UrlGroup);
Settings.Timeouts.SetUrlGroupTimeouts(UrlGroup);
Settings.SetRequestQueueLimit(RequestQueue);
Options.Authentication.SetUrlGroupSecurity(UrlGroup);
Options.Timeouts.SetUrlGroupTimeouts(UrlGroup);
Options.SetRequestQueueLimit(RequestQueue);
_requestQueue.AttachToUrlGroup();
// All resources are set up correctly. Now add all prefixes.
try
{
Settings.UrlPrefixes.RegisterAllPrefixes(UrlGroup);
Options.UrlPrefixes.RegisterAllPrefixes(UrlGroup);
}
catch (WebListenerException)
catch (HttpSysException)
{
// If an error occurred while adding prefixes, free all resources allocated by previous steps.
_requestQueue.DetachFromUrlGroup();
@ -191,7 +189,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
return;
}
Settings.UrlPrefixes.UnregisterAllPrefixes();
Options.UrlPrefixes.UnregisterAllPrefixes();
_state = State.Stopped;
@ -285,7 +283,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
// some other bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
asyncResult.Dispose();
throw new WebListenerException((int)statusCode);
throw new HttpSysException((int)statusCode);
}
}
catch (Exception exception)
@ -310,10 +308,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
internal unsafe bool ValidateAuth(NativeRequestContext requestMemory)
{
if (!Settings.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated())
if (!Options.Authentication.AllowAnonymous && !requestMemory.CheckAuthenticated())
{
SendError(requestMemory.RequestId, StatusCodes.Status401Unauthorized,
AuthenticationManager.GenerateChallenges(Settings.Authentication.Schemes));
AuthenticationManager.GenerateChallenges(Options.Authentication.Schemes));
return false;
}
return true;

View File

@ -7,35 +7,31 @@ using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.Server.HttpSys
{
public class WebListenerSettings
public class HttpSysOptions
{
private const long DefaultRequestQueueLength = 1000; // Http.sys default.
internal static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
// The native request queue
private long _requestQueueLength = DefaultRequestQueueLength;
private RequestQueue _requestQueue;
private ILogger _logger = NullLogger.Instance;
public WebListenerSettings()
public HttpSysOptions()
{
}
/// <summary>
/// The logger that will be used to create the WebListener instance. This should not be changed
/// after creating the listener.
/// The maximum number of concurrent accepts.
/// </summary>
public ILogger Logger
{
get { return _logger; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_logger = value;
}
}
public int MaxAccepts { get; set; } = DefaultMaxAccepts;
/// <summary>
/// Attempts kernel mode caching for responses with eligible headers. The response may not include
/// Set-Cookie, Vary, or Pragma headers. It must include a Cache-Control header with Public and
/// either a Shared-Max-Age or Max-Age value, or an Expires header.
/// </summary>
public bool EnableResponseCaching { get; set; } = true;
/// <summary>
/// The url prefixes to register with Http.Sys. These may be modified at any time prior to disposing

View File

@ -1,23 +0,0 @@
// 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.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Server.HttpSys.Internal
{
public class WebListenerOptionsSetup : IConfigureOptions<WebListenerOptions>
{
private ILoggerFactory _loggerFactory;
public WebListenerOptionsSetup(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
public void Configure(WebListenerOptions options)
{
options.ListenerSettings.Logger = _loggerFactory.CreateLogger<WebListener>();
}
}
}

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
internal class MessagePump : IServer
{
private readonly WebListener _listener;
private readonly HttpSysListener _listener;
private readonly ILogger _logger;
private IHttpApplication<object> _application;
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private readonly ServerAddressesFeature _serverAddresses;
public MessagePump(IOptions<WebListenerOptions> options, ILoggerFactory loggerFactory)
public MessagePump(IOptions<HttpSysOptions> options, ILoggerFactory loggerFactory)
{
if (options == null)
{
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
var optionsInstance = options.Value;
_listener = new WebListener(optionsInstance.ListenerSettings);
_listener = new HttpSysListener(optionsInstance, loggerFactory);
_logger = LogHelper.CreateLogger(loggerFactory, typeof(MessagePump));
Features = new FeatureCollection();
_serverAddresses = new ServerAddressesFeature();
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
_shutdownSignal = new ManualResetEvent(false);
}
internal WebListener Listener
internal HttpSysListener Listener
{
get { return _listener; }
}
@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
_application = new ApplicationWrapper<TContext>(application);
if (_listener.Settings.UrlPrefixes.Count == 0)
if (_listener.Options.UrlPrefixes.Count == 0)
{
throw new InvalidOperationException("No address prefixes were defined.");
}
@ -206,11 +206,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
context.Dispose();
}
private void ParseAddresses(ICollection<string> addresses, WebListener listener)
private void ParseAddresses(ICollection<string> addresses, HttpSysListener listener)
{
foreach (var value in addresses)
{
listener.Settings.UrlPrefixes.Add(UrlPrefix.Create(value));
listener.Options.UrlPrefixes.Add(UrlPrefix.Create(value));
}
}

View File

@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
cts.Cancel();
}
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess)
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion
nativeOverlapped.Dispose();

View File

@ -28,17 +28,17 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
throw new WebListenerException((int)statusCode);
throw new HttpSysException((int)statusCode);
}
// Disabling callbacks when IO operation completes synchronously (returns ErrorCodes.ERROR_SUCCESS)
if (WebListener.SkipIOCPCallbackOnSuccess &&
if (HttpSysListener.SkipIOCPCallbackOnSuccess &&
!UnsafeNclNativeMethods.SetFileCompletionNotificationModes(
requestQueueHandle,
UnsafeNclNativeMethods.FileCompletionNotificationModes.SkipCompletionPortOnSuccess |
UnsafeNclNativeMethods.FileCompletionNotificationModes.SkipSetEventOnHandle))
{
throw new WebListenerException(Marshal.GetLastWin32Error());
throw new HttpSysException(Marshal.GetLastWin32Error());
}
Handle = requestQueueHandle;
@ -94,7 +94,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (result != 0)
{
throw new WebListenerException((int)result);
throw new HttpSysException((int)result);
}
}

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
throw new WebListenerException((int)statusCode);
throw new HttpSysException((int)statusCode);
}
Debug.Assert(serverSessionId != 0, "Invalid id returned by HttpCreateServerSession");

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
throw new WebListenerException((int)statusCode);
throw new HttpSysException((int)statusCode);
}
Debug.Assert(urlGroupId != 0, "Invalid id returned by HttpCreateUrlGroup");
@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
var exception = new WebListenerException((int)statusCode);
var exception = new HttpSysException((int)statusCode);
LogHelper.LogException(_logger, "SetUrlGroupProperty", exception);
if (throwOnError)
{
@ -62,11 +62,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_ALREADY_EXISTS)
{
throw new WebListenerException((int)statusCode, string.Format(Resources.Exception_PrefixAlreadyRegistered, uriPrefix));
throw new HttpSysException((int)statusCode, string.Format(Resources.Exception_PrefixAlreadyRegistered, uriPrefix));
}
else
{
throw new WebListenerException((int)statusCode);
throw new HttpSysException((int)statusCode);
}
}
}

View File

@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Complete(0, null);
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
WebListener.SkipIOCPCallbackOnSuccess)
HttpSysListener.SkipIOCPCallbackOnSuccess)
{
IOCompleted(statusCode, bytesReceived);
}
@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
// Some other bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
// Also ERROR_BAD_DATA if we got it twice or it reported smaller size buffer required.
Fail(new WebListenerException((int)statusCode));
Fail(new HttpSysException((int)statusCode));
}
}
while (retry);
@ -254,7 +254,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
asyncResult._overlapped);
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING ||
(errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && !WebListener.SkipIOCPCallbackOnSuccess))
(errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && !HttpSysListener.SkipIOCPCallbackOnSuccess))
{
return;
}
@ -267,7 +267,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
else if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
asyncResult.Fail(new WebListenerException((int)errorCode));
asyncResult.Fail(new HttpSysException((int)errorCode));
}
else
{
@ -405,7 +405,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
else
{
// It's up to the consumer to fail if the missing ChannelBinding matters to them.
LogHelper.LogException(logger, "GetChannelBindingFromTls", new WebListenerException((int)statusCode));
LogHelper.LogException(logger, "GetChannelBindingFromTls", new HttpSysException((int)statusCode));
break;
}
}

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
var cookedUrl = nativeRequestContext.GetCookedUrl();
QueryString = cookedUrl.GetQueryString() ?? string.Empty;
var prefix = requestContext.Server.Settings.UrlPrefixes.GetPrefix((int)nativeRequestContext.UrlContext);
var prefix = requestContext.Server.Options.UrlPrefixes.GetPrefix((int)nativeRequestContext.UrlContext);
var rawUrlInBytes = _nativeRequestContext.GetRawUrlInBytes();
var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes);

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private CancellationToken? _disconnectToken;
private bool _disposed;
internal RequestContext(WebListener server, NativeRequestContext memoryBlob)
internal RequestContext(HttpSysListener server, NativeRequestContext memoryBlob)
{
// TODO: Verbose log
Server = server;
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
Response = new Response(this);
}
internal WebListener Server { get; }
internal HttpSysListener Server { get; }
internal ILogger Logger => Server.Logger;

View File

@ -170,7 +170,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF)
{
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
Exception exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "Read", exception);
Abort();
throw exception;
@ -265,14 +265,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
else
{
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
Exception exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "BeginRead", exception);
Abort();
throw exception;
}
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
WebListener.SkipIOCPCallbackOnSuccess)
HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
asyncResult.IOCompleted(statusCode, bytesReturned);
@ -391,14 +391,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
else
{
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
Exception exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "ReadAsync", exception);
Abort();
throw exception;
}
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
WebListener.SkipIOCPCallbackOnSuccess)
HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
asyncResult.Dispose();

View File

@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF)
{
asyncResult.Fail(new IOException(string.Empty, new WebListenerException((int)errorCode)));
asyncResult.Fail(new IOException(string.Empty, new HttpSysException((int)errorCode)));
}
else
{

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
_expectedBodyLength = 0;
_nativeStream = null;
_cacheTtl = null;
_authChallenges = RequestContext.Server.Settings.Authentication.Schemes;
_authChallenges = RequestContext.Server.Options.Authentication.Schemes;
}
private enum ResponseState
@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (asyncResult != null &&
statusCode == ErrorCodes.ERROR_SUCCESS &&
WebListener.SkipIOCPCallbackOnSuccess)
HttpSysListener.SkipIOCPCallbackOnSuccess)
{
asyncResult.BytesSent = bytesSent;
// The caller will invoke IOCompleted
@ -394,7 +394,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
if (StatusCode == (ushort)StatusCodes.Status401Unauthorized)
{
RequestContext.Server.Settings.Authentication.SetAuthenticationChallenge(RequestContext);
RequestContext.Server.Options.Authentication.SetAuthenticationChallenge(RequestContext);
}
var flags = HttpApi.HTTP_FLAGS.NONE;
@ -662,7 +662,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
if (errorCode != ErrorCodes.ERROR_SUCCESS)
{
throw new WebListenerException((int)errorCode);
throw new HttpSysException((int)errorCode);
}
}

View File

@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private ILogger Logger => RequestContext.Server.Logger;
internal bool ThrowWriteExceptions => RequestContext.Server.Settings.ThrowWriteExceptions;
internal bool ThrowWriteExceptions => RequestContext.Server.Options.ThrowWriteExceptions;
internal bool IsDisposed => _disposed;
@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{
if (ThrowWriteExceptions)
{
var exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
var exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "Flush", exception);
Abort();
throw exception;
@ -329,7 +329,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
else if (ThrowWriteExceptions)
{
asyncResult.Dispose();
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
Exception exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "FlushAsync", exception);
Abort();
throw exception;
@ -342,7 +342,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
}
if (statusCode == ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess)
if (statusCode == ErrorCodes.ERROR_SUCCESS && HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
asyncResult.IOCompleted(statusCode, bytesSent);
@ -624,7 +624,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
else if (ThrowWriteExceptions)
{
asyncResult.Dispose();
var exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
var exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
LogHelper.LogException(Logger, "SendFileAsync", exception);
Abort();
throw exception;
@ -637,7 +637,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
}
if (statusCode == ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess)
if (statusCode == ErrorCodes.ERROR_SUCCESS && HttpSysListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
asyncResult.IOCompleted(statusCode, bytesSent);

View File

@ -237,7 +237,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
else if (asyncResult._responseStream.ThrowWriteExceptions)
{
var exception = new IOException(string.Empty, new WebListenerException((int)errorCode));
var exception = new IOException(string.Empty, new HttpSysException((int)errorCode));
LogHelper.LogException(logger, "FlushAsync.IOCompleted", exception);
asyncResult.Fail(exception);
}

View File

@ -4,16 +4,14 @@
using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.AspNetCore.Server.HttpSys.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Hosting
{
public static class WebHostBuilderWebListenerExtensions
public static class WebHostBuilderHttpSysExtensions
{
/// <summary>
/// Specify WebListener as the server to be used by the web host.
/// Specify HttpSys as the server to be used by the web host.
/// </summary>
/// <param name="hostBuilder">
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
@ -21,29 +19,28 @@ namespace Microsoft.AspNetCore.Hosting
/// <returns>
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
/// </returns>
public static IWebHostBuilder UseWebListener(this IWebHostBuilder hostBuilder)
public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices(services => {
services.AddTransient<IConfigureOptions<WebListenerOptions>, WebListenerOptionsSetup>();
services.AddSingleton<IServer, MessagePump>();
});
}
/// <summary>
/// Specify WebListener as the server to be used by the web host.
/// Specify HttpSys as the server to be used by the web host.
/// </summary>
/// <param name="hostBuilder">
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
/// </param>
/// <param name="options">
/// A callback to configure WebListener options.
/// A callback to configure HttpSys options.
/// </param>
/// <returns>
/// The Microsoft.AspNetCore.Hosting.IWebHostBuilder.
/// </returns>
public static IWebHostBuilder UseWebListener(this IWebHostBuilder hostBuilder, Action<WebListenerOptions> options)
public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder, Action<HttpSysOptions> options)
{
return hostBuilder.UseWebListener().ConfigureServices(services =>
return hostBuilder.UseHttpSys().ConfigureServices(services =>
{
services.Configure(options);
});

View File

@ -1,29 +0,0 @@
// 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.AspNetCore.Server.HttpSys
{
public class WebListenerOptions
{
internal static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
/// <summary>
/// Settings for the underlying WebListener instance.
/// </summary>
public WebListenerSettings ListenerSettings { get; } = new WebListenerSettings();
/// <summary>
/// The maximum number of concurrent calls to WebListener.AcceptAsync().
/// </summary>
public int MaxAccepts { get; set; } = DefaultMaxAccepts;
/// <summary>
/// Attempts kernel mode caching for responses with eligible headers. The response may not include
/// Set-Cookie, Vary, or Pragma headers. It must include a Cache-Control header with Public and
/// either a Shared-Max-Age or Max-Age value, or an Expires header.
/// </summary>
public bool EnableResponseCaching { get; set; } = true;
}
}

View File

@ -4,7 +4,8 @@
"packOptions": {
"tags": [
"aspnetcore",
"weblistener"
"weblistener",
"httpsys"
]
},
"dependencies": {

View File

@ -8,6 +8,7 @@ using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
namespace Microsoft.AspNetCore.Server.HttpSys.Listener
@ -147,13 +148,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string root;
var server = Utilities.CreateHttpServerReturnRoot("/", out root);
server.Dispose();
server = new WebListener();
server = new HttpSysListener(new HttpSysOptions(), new LoggerFactory());
using (server)
{
var uriBuilder = new UriBuilder(root);
foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" })
{
server.Settings.UrlPrefixes.Add(UrlPrefix.Create(uriBuilder.Scheme, uriBuilder.Host, uriBuilder.Port, path));
server.Options.UrlPrefixes.Add(UrlPrefix.Create(uriBuilder.Scheme, uriBuilder.Host, uriBuilder.Port, path));
}
server.Start();

View File

@ -272,7 +272,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -331,7 +331,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -374,7 +374,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var cts = new CancellationTokenSource();
var responseTask = SendRequestAsync(address, cts.Token);
@ -404,7 +404,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var cts = new CancellationTokenSource();
var responseTask = SendRequestAsync(address, cts.Token);
@ -482,7 +482,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
RequestContext context;
using (var client = new HttpClient())
{
@ -516,7 +516,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
RequestContext context;
using (var client = new HttpClient())
{

View File

@ -352,7 +352,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -411,7 +411,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -454,7 +454,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
var cts = new CancellationTokenSource();
var responseTask = SendRequestAsync(address, cts.Token);
@ -510,7 +510,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.ThrowWriteExceptions = true;
server.Options.ThrowWriteExceptions = true;
RequestContext context;
using (var client = new HttpClient())
{

View File

@ -234,7 +234,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
string address;
using (var server = Utilities.CreateHttpServer(out address))
{
server.Settings.RequestQueueLimit = 1001;
server.Options.RequestQueueLimit = 1001;
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -262,7 +262,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
Assert.Equal(string.Empty, response);
address += "pathbase/";
server.Settings.UrlPrefixes.Add(address);
server.Options.UrlPrefixes.Add(address);
responseTask = SendRequestAsync(address);
@ -283,7 +283,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
using (var server = Utilities.CreateHttpServer(out address))
{
address += "pathbase/";
server.Settings.UrlPrefixes.Add(address);
server.Options.UrlPrefixes.Add(address);
var responseTask = SendRequestAsync(address);
var context = await server.AcceptAsync(Utilities.DefaultTimeout);
@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
var response = await responseTask;
Assert.Equal(string.Empty, response);
Assert.True(server.Settings.UrlPrefixes.Remove(address));
Assert.True(server.Options.UrlPrefixes.Remove(address));
responseTask = SendRequestAsync(address);

View File

@ -5,14 +5,14 @@ using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.HttpSys.Listener
{
internal static class Utilities
{
// When tests projects are run in parallel, overlapping port ranges can cause a race condition when looking for free
// ports during dynamic port allocation. To avoid this, make sure the port range here is different from the range in
// Microsoft.AspNetCore.Server.WebListener.
// ports during dynamic port allocation.
private const int BasePort = 8001;
private const int MaxPort = 11000;
private static int NextPort = BasePort;
@ -33,27 +33,27 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
#endif
}
internal static WebListener CreateHttpAuthServer(AuthenticationSchemes authScheme, bool allowAnonymos, out string baseAddress)
internal static HttpSysListener CreateHttpAuthServer(AuthenticationSchemes authScheme, bool allowAnonymos, out string baseAddress)
{
var listener = CreateHttpServer(out baseAddress);
listener.Settings.Authentication.Schemes = authScheme;
listener.Settings.Authentication.AllowAnonymous = allowAnonymos;
listener.Options.Authentication.Schemes = authScheme;
listener.Options.Authentication.AllowAnonymous = allowAnonymos;
return listener;
}
internal static WebListener CreateHttpServer(out string baseAddress)
internal static HttpSysListener CreateHttpServer(out string baseAddress)
{
string root;
return CreateDynamicHttpServer(string.Empty, out root, out baseAddress);
}
internal static WebListener CreateHttpServerReturnRoot(string path, out string root)
internal static HttpSysListener CreateHttpServerReturnRoot(string path, out string root)
{
string baseAddress;
return CreateDynamicHttpServer(path, out root, out baseAddress);
}
internal static WebListener CreateDynamicHttpServer(string basePath, out string root, out string baseAddress)
internal static HttpSysListener CreateDynamicHttpServer(string basePath, out string root, out string baseAddress)
{
lock (PortLock)
{
@ -63,14 +63,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
var prefix = UrlPrefix.Create("http", "localhost", port, basePath);
root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port;
baseAddress = prefix.ToString();
var listener = new WebListener();
listener.Settings.UrlPrefixes.Add(prefix);
var listener = new HttpSysListener(new HttpSysOptions(), new LoggerFactory());
listener.Options.UrlPrefixes.Add(prefix);
try
{
listener.Start();
return listener;
}
catch (WebListenerException)
catch (HttpSysException)
{
listener.Dispose();
}
@ -80,15 +80,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
throw new Exception("Failed to locate a free port.");
}
internal static WebListener CreateHttpsServer()
internal static HttpSysListener CreateHttpsServer()
{
return CreateServer("https", "localhost", 9090, string.Empty);
}
internal static WebListener CreateServer(string scheme, string host, int port, string path)
internal static HttpSysListener CreateServer(string scheme, string host, int port, string path)
{
WebListener listener = new WebListener();
listener.Settings.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path));
var listener = new HttpSysListener(new HttpSysOptions(), new LoggerFactory());
listener.Options.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path));
listener.Start();
return listener;
}
@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
/// AcceptAsync extension with timeout. This extension should be used in all tests to prevent
/// unexpected hangs when a request does not arrive.
/// </summary>
internal static async Task<RequestContext> AcceptAsync(this WebListener server, TimeSpan timeout)
internal static async Task<RequestContext> AcceptAsync(this HttpSysListener server, TimeSpan timeout)
{
var acceptTask = server.AcceptAsync();
var completedTask = await Task.WhenAny(acceptTask, Task.Delay(timeout));

View File

@ -305,11 +305,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
var dynamicServer = Utilities.CreateHttpServerReturnRoot("/", out root, app);
dynamicServer.Dispose();
var rootUri = new Uri(root);
var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory());
foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" })
{
server.Listener.Settings.UrlPrefixes.Add(UrlPrefix.Create(rootUri.Scheme, rootUri.Host, rootUri.Port, path));
server.Listener.Options.UrlPrefixes.Add(UrlPrefix.Create(rootUri.Scheme, rootUri.Host, rootUri.Port, path));
}
server.Start(new DummyApplication(app));

View File

@ -241,9 +241,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
string address;
using (Utilities.CreateHttpServer(out address, httpContext => Task.FromResult(0))) { }
var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
server.Listener.Settings.UrlPrefixes.Add(UrlPrefix.Create(address));
server.Listener.Settings.RequestQueueLimit = 1001;
var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory());
server.Listener.Options.UrlPrefixes.Add(UrlPrefix.Create(address));
server.Listener.Options.RequestQueueLimit = 1001;
using (server)
{

View File

@ -13,8 +13,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
internal static class Utilities
{
// When tests projects are run in parallel, overlapping port ranges can cause a race condition when looking for free
// ports during dynamic port allocation. To avoid this, make sure the port range here is different from the range in
// Microsoft.Net.Http.Server.
// ports during dynamic port allocation.
private const int BasePort = 5001;
private const int MaxPort = 8000;
private static int NextPort = BasePort;
@ -50,16 +49,16 @@ namespace Microsoft.AspNetCore.Server.HttpSys
root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port;
baseAddress = prefix.ToString();
var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory());
server.Features.Get<IServerAddressesFeature>().Addresses.Add(baseAddress);
server.Listener.Settings.Authentication.Schemes = authType;
server.Listener.Settings.Authentication.AllowAnonymous = allowAnonymous;
server.Listener.Options.Authentication.Schemes = authType;
server.Listener.Options.Authentication.AllowAnonymous = allowAnonymous;
try
{
server.Start(new DummyApplication(app));
return server;
}
catch (WebListenerException)
catch (HttpSysException)
{
}
}
@ -75,7 +74,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
internal static IServer CreateServer(string scheme, string host, int port, string path, RequestDelegate app)
{
var server = new MessagePump(Options.Create(new WebListenerOptions()), new LoggerFactory());
var server = new MessagePump(Options.Create(new HttpSysOptions()), new LoggerFactory());
server.Features.Get<IServerAddressesFeature>().Addresses.Add(UrlPrefix.Create(scheme, host, port, path).ToString());
server.Start(new DummyApplication(app));
return server;

View File

@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
[InlineData("http://www.example.com:NOTAPORT")]
[InlineData("https://www.example.com:NOTAPORT")]
[InlineData("http://www.example.com:NOTAPORT/")]
[InlineData("http://foo:/tmp/weblistener-test.sock:5000/doesn't/matter")]
[InlineData("http://foo:/tmp/httpsys-test.sock:5000/doesn't/matter")]
public void CreateThrowsForUrlsWithInvalidPorts(string url)
{
Assert.Throws<FormatException>(() => UrlPrefix.Create(url));