API cleaup, organization

This commit is contained in:
Chris R 2016-07-27 10:29:15 -07:00
parent 3d2e1c4d3e
commit 235ac59551
34 changed files with 495 additions and 739 deletions

View File

@ -18,13 +18,13 @@ namespace HelloWorld
{ {
using (WebListener listener = new WebListener()) using (WebListener listener = new WebListener())
{ {
listener.UrlPrefixes.Add(UrlPrefix.Create("http://localhost:8080")); listener.UrlPrefixes.Add("http://localhost:8080");
listener.Start(); listener.Start();
Console.WriteLine("Running..."); Console.WriteLine("Running...");
while (true) while (true)
{ {
RequestContext context = await listener.GetContextAsync(); RequestContext context = await listener.AcceptAsync();
Console.WriteLine("Accepted"); Console.WriteLine("Accepted");
// Context: // Context:

View File

@ -2,8 +2,6 @@ using System;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Server; using Microsoft.Net.Http.Server;

View File

@ -5,7 +5,6 @@ using System.Threading;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.WebListener; using Microsoft.AspNetCore.Server.WebListener;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
internal AuthenticationHandler(RequestContext requestContext) internal AuthenticationHandler(RequestContext requestContext)
{ {
_requestContext = requestContext; _requestContext = requestContext;
_authSchemes = requestContext.AuthenticationChallenges; _authSchemes = requestContext.Response.AuthenticationChallenges;
_customChallenges = AuthenticationSchemes.None; _customChallenges = AuthenticationSchemes.None;
} }
@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
} }
} }
// A challenge was issued, it overrides any pre-set auth types. // A challenge was issued, it overrides any pre-set auth types.
_requestContext.AuthenticationChallenges = _customChallenges; _requestContext.Response.AuthenticationChallenges = _customChallenges;
return Task.FromResult(0); return Task.FromResult(0);
} }

View File

@ -323,7 +323,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
internal ITlsConnectionFeature GetTlsConnectionFeature() internal ITlsConnectionFeature GetTlsConnectionFeature()
{ {
return Request.IsSecureConnection ? this : null; return Request.IsHttps ? this : null;
} }
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId() byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId()
@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
internal ITlsTokenBindingFeature GetTlsTokenBindingFeature() internal ITlsTokenBindingFeature GetTlsTokenBindingFeature()
{ {
return Request.IsSecureConnection ? this : null; return Request.IsHttps ? this : null;
} }
void IHttpBufferingFeature.DisableRequestBuffering() void IHttpBufferingFeature.DisableRequestBuffering()

View File

@ -15,7 +15,6 @@
// See the Apache 2 License for the specific language governing // See the Apache 2 License for the specific language governing
// permissions and limitations under the License. // permissions and limitations under the License.
using System;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;

View File

@ -29,10 +29,8 @@ using Microsoft.Net.Http.Server;
namespace Microsoft.AspNetCore.Server.WebListener namespace Microsoft.AspNetCore.Server.WebListener
{ {
public class MessagePump : IServer internal class MessagePump : IServer
{ {
private static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
private readonly Microsoft.Net.Http.Server.WebListener _listener; private readonly Microsoft.Net.Http.Server.WebListener _listener;
private readonly ILogger _logger; private readonly ILogger _logger;
@ -48,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
private readonly ServerAddressesFeature _serverAddresses; private readonly ServerAddressesFeature _serverAddresses;
public MessagePump(IOptions<WebListenerOptions> options, ILoggerFactory loggerFactory) internal MessagePump(IOptions<WebListenerOptions> options, ILoggerFactory loggerFactory)
{ {
if (options == null) if (options == null)
{ {
@ -66,32 +64,17 @@ namespace Microsoft.AspNetCore.Server.WebListener
Features.Set<IServerAddressesFeature>(_serverAddresses); Features.Set<IServerAddressesFeature>(_serverAddresses);
_processRequest = new Action<object>(ProcessRequestAsync); _processRequest = new Action<object>(ProcessRequestAsync);
_maxAccepts = DefaultMaxAccepts; _maxAccepts = options.Value?.MaxAccepts ?? WebListenerOptions.DefaultMaxAccepts;
EnableResponseCaching = options.Value?.EnableResponseCaching ?? true;
_shutdownSignal = new ManualResetEvent(false); _shutdownSignal = new ManualResetEvent(false);
} }
public Microsoft.Net.Http.Server.WebListener Listener internal Microsoft.Net.Http.Server.WebListener Listener
{ {
get { return _listener; } get { return _listener; }
} }
internal int MaxAccepts internal bool EnableResponseCaching { get; set; }
{
get
{
return _maxAccepts;
}
set
{
_maxAccepts = value;
if (_listener.IsListening)
{
ActivateRequestProcessingLimits();
}
}
}
internal bool EnableResponseCaching { get; set; } = true;
public IFeatureCollection Features { get; } public IFeatureCollection Features { get; }
@ -123,7 +106,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
private void ActivateRequestProcessingLimits() private void ActivateRequestProcessingLimits()
{ {
for (int i = _acceptorCounts; i < MaxAccepts; i++) for (int i = _acceptorCounts; i < _maxAccepts; i++)
{ {
ProcessRequestsWorker(); ProcessRequestsWorker();
} }
@ -136,13 +119,13 @@ namespace Microsoft.AspNetCore.Server.WebListener
private async void ProcessRequestsWorker() private async void ProcessRequestsWorker()
{ {
int workerIndex = Interlocked.Increment(ref _acceptorCounts); int workerIndex = Interlocked.Increment(ref _acceptorCounts);
while (!_stopping && workerIndex <= MaxAccepts) while (!_stopping && workerIndex <= _maxAccepts)
{ {
// Receive a request // Receive a request
RequestContext requestContext; RequestContext requestContext;
try try
{ {
requestContext = await _listener.GetContextAsync().SupressContext(); requestContext = await _listener.AcceptAsync().SupressContext();
} }
catch (Exception exception) catch (Exception exception)
{ {
@ -237,7 +220,6 @@ namespace Microsoft.AspNetCore.Server.WebListener
} }
} }
public void Dispose() public void Dispose()
{ {
_stopping = true; _stopping = true;

View File

@ -3,9 +3,11 @@
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using System.Runtime.CompilerServices;
[assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")] [assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")] [assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")] [assembly: AssemblyProduct("Microsoft ASP.NET Core")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Server.WebListener.FunctionalTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -16,9 +16,6 @@
// permissions and limitations under the License. // permissions and limitations under the License.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.WebListener; using Microsoft.AspNetCore.Server.WebListener;
using Microsoft.AspNetCore.Server.WebListener.Internal; using Microsoft.AspNetCore.Server.WebListener.Internal;

View File

@ -16,14 +16,17 @@
// permissions and limitations under the License. // permissions and limitations under the License.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Server.WebListener namespace Microsoft.AspNetCore.Server.WebListener
{ {
public class WebListenerOptions public class WebListenerOptions
{ {
internal static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
public Microsoft.Net.Http.Server.WebListener Listener { get; set; } = new Microsoft.Net.Http.Server.WebListener(); public Microsoft.Net.Http.Server.WebListener Listener { get; set; } = new Microsoft.Net.Http.Server.WebListener();
public int MaxAccepts { get; set; } = DefaultMaxAccepts;
public bool EnableResponseCaching { get; set; } = true;
} }
} }

View File

@ -144,7 +144,7 @@ namespace Microsoft.Net.Http.Server
internal void SetAuthenticationChallenge(RequestContext context) internal void SetAuthenticationChallenge(RequestContext context)
{ {
IList<string> challenges = GenerateChallenges(context.AuthenticationChallenges); IList<string> challenges = GenerateChallenges(context.Response.AuthenticationChallenges);
if (challenges.Count > 0) if (challenges.Count > 0)
{ {

View File

@ -1105,7 +1105,8 @@ namespace Microsoft.Net.Http.Server
} }
} }
private static unsafe string GetVerb(HTTP_REQUEST* request, long fixup) // This requires the HTTP_REQUEST to still be pinned in its original location.
internal static unsafe string GetVerb(HTTP_REQUEST* request)
{ {
string verb = null; string verb = null;
@ -1115,31 +1116,7 @@ namespace Microsoft.Net.Http.Server
} }
else if (request->Verb == HTTP_VERB.HttpVerbUnknown && request->pUnknownVerb != null) else if (request->Verb == HTTP_VERB.HttpVerbUnknown && request->pUnknownVerb != null)
{ {
verb = HeaderEncoding.GetString(request->pUnknownVerb + fixup, request->UnknownVerbLength); verb = HeaderEncoding.GetString(request->pUnknownVerb, request->UnknownVerbLength);
}
return verb;
}
internal static unsafe string GetVerb(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
{
fixed (byte* pMemoryBlob = memoryBlob)
{
return GetVerb((HTTP_REQUEST*)(pMemoryBlob + requestOffset), pMemoryBlob - (byte*)originalAddress);
}
}
internal static HTTP_VERB GetKnownVerb(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
{
// Return value.
HTTP_VERB verb = HTTP_VERB.HttpVerbUnknown;
fixed (byte* pMemoryBlob = memoryBlob)
{
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnparsed && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum)
{
verb = request->Verb;
}
} }
return verb; return verb;

View File

@ -67,10 +67,12 @@ namespace Microsoft.Net.Http.Server
if (cancellationToken.CanBeCanceled) if (cancellationToken.CanBeCanceled)
{ {
_cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext); _cancellationRegistration = RequestContext.RegisterForCancellation(cancellationToken);
} }
} }
internal SafeHandle RequestQueueHandle => _requestContext.Server.RequestQueue.Handle;
internal X509Certificate2 ClientCert internal X509Certificate2 ClientCert
{ {
get get
@ -184,8 +186,8 @@ namespace Microsoft.Net.Http.Server
uint statusCode = uint statusCode =
UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(
RequestContext.RequestQueueHandle, RequestQueueHandle,
RequestContext.Request.ConnectionId, RequestContext.Request.UConnectionId,
(uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE, (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE,
RequestBlob, RequestBlob,
size, size,
@ -263,8 +265,8 @@ namespace Microsoft.Net.Http.Server
uint bytesReceived = 0; uint bytesReceived = 0;
errorCode = errorCode =
UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate( UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(
requestContext.RequestQueueHandle, requestContext.Server.RequestQueue.Handle,
requestContext.Request.ConnectionId, requestContext.Request.UConnectionId,
(uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE, (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE,
asyncResult._memoryBlob, asyncResult._memoryBlob,
asyncResult._size, asyncResult._size,

View File

@ -22,48 +22,25 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.Net.Http.Server namespace Microsoft.Net.Http.Server
{ {
public sealed class Request public sealed class Request
{ {
private RequestContext _requestContext;
private NativeRequestContext _nativeRequestContext; private NativeRequestContext _nativeRequestContext;
private ulong _requestId;
private ulong _connectionId;
private ulong _contextId;
private SslStatus _sslStatus;
private string _httpMethod;
private Version _httpVersion;
// private Uri _requestUri;
private string _rawUrl;
private string _cookedUrlHost;
private string _cookedUrlPath;
private string _cookedUrlQuery;
private string _pathBase;
private string _path;
private X509Certificate2 _clientCert; private X509Certificate2 _clientCert;
private byte[] _providedTokenBindingId; private byte[] _providedTokenBindingId;
private byte[] _referredTokenBindingId; private byte[] _referredTokenBindingId;
private HeaderCollection _headers;
private BoundaryType _contentBoundaryType; private BoundaryType _contentBoundaryType;
private long? _contentLength; private long? _contentLength;
private Stream _nativeStream; private Stream _nativeStream;
@ -71,116 +48,90 @@ namespace Microsoft.Net.Http.Server
private SocketAddress _localEndPoint; private SocketAddress _localEndPoint;
private SocketAddress _remoteEndPoint; private SocketAddress _remoteEndPoint;
private ClaimsPrincipal _user;
private bool _isDisposed = false; private bool _isDisposed = false;
internal unsafe Request(RequestContext httpContext, NativeRequestContext memoryBlob) internal unsafe Request(RequestContext requestContext, NativeRequestContext memoryBlob)
{ {
// TODO: Verbose log // TODO: Verbose log
_requestContext = httpContext; RequestContext = requestContext;
_nativeRequestContext = memoryBlob; _nativeRequestContext = memoryBlob;
_contentBoundaryType = BoundaryType.None; _contentBoundaryType = BoundaryType.None;
// Set up some of these now to avoid refcounting on memory blob later. // Set up some of these now to avoid refcounting on memory blob later.
_requestId = memoryBlob.RequestBlob->RequestId; RequestId = memoryBlob.RequestBlob->RequestId;
_connectionId = memoryBlob.RequestBlob->ConnectionId; UConnectionId = memoryBlob.RequestBlob->ConnectionId;
_contextId = memoryBlob.RequestBlob->UrlContext; SslStatus = memoryBlob.RequestBlob->pSslInfo == null ? SslStatus.Insecure :
_sslStatus = memoryBlob.RequestBlob->pSslInfo == null ? SslStatus.Insecure :
memoryBlob.RequestBlob->pSslInfo->SslClientCertNegotiated == 0 ? SslStatus.NoClientCert : memoryBlob.RequestBlob->pSslInfo->SslClientCertNegotiated == 0 ? SslStatus.NoClientCert :
SslStatus.ClientCert; SslStatus.ClientCert;
if (memoryBlob.RequestBlob->pRawUrl != null && memoryBlob.RequestBlob->RawUrlLength > 0) if (memoryBlob.RequestBlob->pRawUrl != null && memoryBlob.RequestBlob->RawUrlLength > 0)
{ {
_rawUrl = Marshal.PtrToStringAnsi((IntPtr)memoryBlob.RequestBlob->pRawUrl, memoryBlob.RequestBlob->RawUrlLength); RawUrl = Marshal.PtrToStringAnsi((IntPtr)memoryBlob.RequestBlob->pRawUrl, memoryBlob.RequestBlob->RawUrlLength);
} }
UnsafeNclNativeMethods.HttpApi.HTTP_COOKED_URL cookedUrl = memoryBlob.RequestBlob->CookedUrl; UnsafeNclNativeMethods.HttpApi.HTTP_COOKED_URL cookedUrl = memoryBlob.RequestBlob->CookedUrl;
if (cookedUrl.pHost != null && cookedUrl.HostLength > 0) if (cookedUrl.pHost != null && cookedUrl.HostLength > 0)
{ {
_cookedUrlHost = Marshal.PtrToStringUni((IntPtr)cookedUrl.pHost, cookedUrl.HostLength / 2); // TODO: Unused
// _cookedUrlHost = Marshal.PtrToStringUni((IntPtr)cookedUrl.pHost, cookedUrl.HostLength / 2);
} }
var cookedUrlPath = string.Empty;
if (cookedUrl.pAbsPath != null && cookedUrl.AbsPathLength > 0) if (cookedUrl.pAbsPath != null && cookedUrl.AbsPathLength > 0)
{ {
_cookedUrlPath = Marshal.PtrToStringUni((IntPtr)cookedUrl.pAbsPath, cookedUrl.AbsPathLength / 2); cookedUrlPath = Marshal.PtrToStringUni((IntPtr)cookedUrl.pAbsPath, cookedUrl.AbsPathLength / 2);
} }
QueryString = string.Empty;
if (cookedUrl.pQueryString != null && cookedUrl.QueryStringLength > 0) if (cookedUrl.pQueryString != null && cookedUrl.QueryStringLength > 0)
{ {
_cookedUrlQuery = Marshal.PtrToStringUni((IntPtr)cookedUrl.pQueryString, cookedUrl.QueryStringLength / 2); QueryString = Marshal.PtrToStringUni((IntPtr)cookedUrl.pQueryString, cookedUrl.QueryStringLength / 2);
} }
UrlPrefix prefix = httpContext.Server.UrlPrefixes.GetPrefix((int)_contextId); var prefix = requestContext.Server.UrlPrefixes.GetPrefix((int)memoryBlob.RequestBlob->UrlContext);
string originalPath = RequestPath; var originalPath = RequestUriBuilder.GetRequestPath(RawUrl, cookedUrlPath, RequestContext.Logger);
// These paths are both unescaped already. // These paths are both unescaped already.
if (originalPath.Length == prefix.Path.Length - 1) if (originalPath.Length == prefix.Path.Length - 1)
{ {
// They matched exactly except for the trailing slash. // They matched exactly except for the trailing slash.
_pathBase = originalPath; PathBase = originalPath;
_path = string.Empty; Path = string.Empty;
} }
else else
{ {
// url: /base/path, prefix: /base/, base: /base, path: /path // url: /base/path, prefix: /base/, base: /base, path: /path
// url: /, prefix: /, base: , path: / // url: /, prefix: /, base: , path: /
_pathBase = originalPath.Substring(0, prefix.Path.Length - 1); PathBase = originalPath.Substring(0, prefix.Path.Length - 1);
_path = originalPath.Substring(prefix.Path.Length - 1); Path = originalPath.Substring(prefix.Path.Length - 1);
} }
int major = memoryBlob.RequestBlob->Version.MajorVersion; int major = memoryBlob.RequestBlob->Version.MajorVersion;
int minor = memoryBlob.RequestBlob->Version.MinorVersion; int minor = memoryBlob.RequestBlob->Version.MinorVersion;
if (major == 1 && minor == 1) if (major == 1 && minor == 1)
{ {
_httpVersion = Constants.V1_1; ProtocolVersion = Constants.V1_1;
} }
else if (major == 1 && minor == 0) else if (major == 1 && minor == 0)
{ {
_httpVersion = Constants.V1_0; ProtocolVersion = Constants.V1_0;
} }
else else
{ {
_httpVersion = new Version(major, minor); ProtocolVersion = new Version(major, minor);
} }
_httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, BufferAlignment, OriginalBlobAddress); KnownMethod = memoryBlob.RequestBlob->Verb;
_headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext)); Method = UnsafeNclNativeMethods.HttpApi.GetVerb(memoryBlob.RequestBlob);
Headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext));
var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob; var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob;
_user = AuthenticationManager.GetUser(requestV2->pRequestInfo, requestV2->RequestInfoCount); User = AuthenticationManager.GetUser(requestV2->pRequestInfo, requestV2->RequestInfoCount);
GetTlsTokenBindingInfo(); GetTlsTokenBindingInfo();
// Finished directly accessing the HTTP_REQUEST structure.
_nativeRequestContext.ReleasePins();
// TODO: Verbose log parameters // TODO: Verbose log parameters
} }
internal SslStatus SslStatus
{
get
{
return _sslStatus;
}
}
public ulong ConnectionId
{
get
{
return _connectionId;
}
}
internal ulong ContextId
{
get { return _contextId; }
}
internal RequestContext RequestContext
{
get
{
return _requestContext;
}
}
internal byte[] RequestBuffer internal byte[] RequestBuffer
{ {
get get
@ -208,26 +159,19 @@ namespace Microsoft.Net.Http.Server
} }
} }
// With the leading ?, if any internal ulong UConnectionId { get; }
public string QueryString
{
get
{
return _cookedUrlQuery ?? string.Empty;
}
set
{
_cookedUrlQuery = value;
}
}
internal ulong RequestId // No ulongs in public APIs...
{ public long ConnectionId => (long)UConnectionId;
get
{ internal ulong RequestId { get; }
return _requestId;
} private SslStatus SslStatus { get; }
}
private RequestContext RequestContext { get; }
// With the leading ?, if any
public string QueryString { get; }
public long? ContentLength public long? ContentLength
{ {
@ -261,20 +205,13 @@ namespace Microsoft.Net.Http.Server
} }
} }
public HeaderCollection Headers public HeaderCollection Headers { get; }
{
get { return _headers; }
}
public string Method private UnsafeNclNativeMethods.HttpApi.HTTP_VERB KnownMethod { get; }
{
get { return _httpMethod; }
}
public bool IsHeadMethod public bool IsHeadMethod => KnownMethod == UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD;
{
get { return string.Equals(_httpMethod, "HEAD", StringComparison.OrdinalIgnoreCase); } public string Method { get; }
}
public Stream Body public Stream Body
{ {
@ -288,39 +225,15 @@ namespace Microsoft.Net.Http.Server
} }
} }
public string PathBase public string PathBase { get; }
{
get { return _pathBase; }
}
public string Path public string Path { get; }
{
get { return _path; }
}
public bool IsSecureConnection public bool IsHttps => SslStatus != SslStatus.Insecure;
{
get
{
return _sslStatus != SslStatus.Insecure;
}
}
public string RawUrl public string RawUrl { get; }
{
get
{
return _rawUrl;
}
}
public Version ProtocolVersion public Version ProtocolVersion { get; }
{
get
{
return _httpVersion;
}
}
public bool HasEntityBody public bool HasEntityBody
{ {
@ -358,65 +271,24 @@ namespace Microsoft.Net.Http.Server
} }
} }
public IPAddress RemoteIpAddress // TODO: Lazy cache?
{ public IPAddress RemoteIpAddress => RemoteEndPoint.GetIPAddress();
get { return RemoteEndPoint.GetIPAddress(); }
}
public IPAddress LocalIpAddress public IPAddress LocalIpAddress => LocalEndPoint.GetIPAddress();
{
get { return LocalEndPoint.GetIPAddress(); }
}
public int RemotePort public int RemotePort => RemoteEndPoint.GetPort();
{
get { return RemoteEndPoint.GetPort(); }
}
public int LocalPort public int LocalPort => LocalEndPoint.GetPort();
{
get { return LocalEndPoint.GetPort(); }
}
public string Scheme public string Scheme => IsHttps ? Constants.HttpsScheme : Constants.HttpScheme;
{
get { return IsSecureConnection ? Constants.HttpsScheme : Constants.HttpScheme; }
}
internal string RequestPath // HTTP.Sys allows you to upgrade anything to opaque unless content-length > 0 or chunked are specified.
{ // TODO: >= Win8 check https://github.com/aspnet/WebListener/issues/215
get internal bool IsUpgradable => !HasEntityBody;
{
return RequestUriBuilder.GetRequestPath(_rawUrl, _cookedUrlPath, RequestContext.Logger);
}
}
internal bool IsUpgradable public string ContentType => Headers[HttpKnownHeaderNames.ContentType];
{
get
{
// HTTP.Sys allows you to upgrade anything to opaque unless content-length > 0 or chunked are specified.
return !HasEntityBody;
}
}
public string ContentType internal ClaimsPrincipal User { get; }
{
get
{
return Headers[HttpKnownHeaderNames.ContentType];
}
}
internal ClaimsPrincipal User
{
get { return _user; }
}
internal UnsafeNclNativeMethods.HttpApi.HTTP_VERB GetKnownMethod()
{
return UnsafeNclNativeMethods.HttpApi.GetKnownVerb(RequestBuffer, BufferAlignment, OriginalBlobAddress);
}
// Populates the client certificate. The result may be null if there is no client cert. // Populates the client certificate. The result may be null if there is no client cert.
// TODO: Does it make sense for this to be invoked multiple times (e.g. renegotiate)? Client and server code appear to // TODO: Does it make sense for this to be invoked multiple times (e.g. renegotiate)? Client and server code appear to
@ -435,7 +307,7 @@ namespace Microsoft.Net.Http.Server
} }
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
ClientCertLoader certLoader = new ClientCertLoader(RequestContext, cancellationToken); var certLoader = new ClientCertLoader(RequestContext, cancellationToken);
try try
{ {
await certLoader.LoadClientCertificateAsync().SupressContext(); await certLoader.LoadClientCertificateAsync().SupressContext();
@ -489,40 +361,19 @@ namespace Microsoft.Net.Http.Server
} }
} }
// Use this to save the blob from dispose if this object was never used (never given to a user) and is about to be
// disposed.
internal void DetachBlob(NativeRequestContext memoryBlob)
{
if (memoryBlob != null && (object)memoryBlob == (object)_nativeRequestContext)
{
_nativeRequestContext = null;
}
}
// Finalizes ownership of the memory blob. DetachBlob can't be called after this.
internal void ReleasePins()
{
_nativeRequestContext.ReleasePins();
}
// should only be called from RequestContext // should only be called from RequestContext
internal void Dispose() internal void Dispose()
{ {
// TODO: Verbose log // TODO: Verbose log
_isDisposed = true; _isDisposed = true;
NativeRequestContext memoryBlob = _nativeRequestContext; _nativeRequestContext.Dispose();
if (memoryBlob != null)
{
memoryBlob.Dispose();
_nativeRequestContext = null;
}
if (_nativeStream != null) if (_nativeStream != null)
{ {
_nativeStream.Dispose(); _nativeStream.Dispose();
} }
} }
internal void CheckDisposed() private void CheckDisposed()
{ {
if (_isDisposed) if (_isDisposed)
{ {

View File

@ -23,9 +23,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Security.Authentication.ExtendedProtection; using System.Security.Authentication.ExtendedProtection;
using System.Security.Claims; using System.Security.Claims;
using System.Threading; using System.Threading;
@ -36,47 +34,31 @@ namespace Microsoft.Net.Http.Server
{ {
public sealed class RequestContext : IDisposable public sealed class RequestContext : IDisposable
{ {
internal static readonly Action<object> AbortDelegate = Abort; private static readonly Action<object> AbortDelegate = Abort;
private WebListener _server;
private Request _request;
private Response _response;
private NativeRequestContext _memoryBlob; private NativeRequestContext _memoryBlob;
private bool _disposed;
private CancellationTokenSource _requestAbortSource; private CancellationTokenSource _requestAbortSource;
private CancellationToken? _disconnectToken; private CancellationToken? _disconnectToken;
private bool _disposed;
internal RequestContext(WebListener server, NativeRequestContext memoryBlob) internal RequestContext(WebListener server, NativeRequestContext memoryBlob)
{ {
// TODO: Verbose log // TODO: Verbose log
_server = server; Server = server;
_memoryBlob = memoryBlob; _memoryBlob = memoryBlob;
_request = new Request(this, _memoryBlob); Request = new Request(this, _memoryBlob);
_response = new Response(this); Response = new Response(this);
_request.ReleasePins();
AuthenticationChallenges = server.AuthenticationManager.AuthenticationSchemes & ~AuthenticationSchemes.AllowAnonymous;
} }
public Request Request internal WebListener Server { get; }
{
get
{
return _request;
}
}
public Response Response internal ILogger Logger => Server.Logger;
{
get
{
return _response;
}
}
public ClaimsPrincipal User public Request Request { get; }
{
get { return _request.User; } public Response Response { get; }
}
public ClaimsPrincipal User => Request.User;
public CancellationToken DisconnectToken public CancellationToken DisconnectToken
{ {
@ -86,7 +68,7 @@ namespace Microsoft.Net.Http.Server
// We need to be able to dispose of the registrations each request to prevent leaks. // We need to be able to dispose of the registrations each request to prevent leaks.
if (!_disconnectToken.HasValue) if (!_disconnectToken.HasValue)
{ {
var connectionDisconnectToken = _server.DisconnectListener.GetTokenForConnection(Request.ConnectionId); var connectionDisconnectToken = Server.DisconnectListener.GetTokenForConnection(Request.UConnectionId);
if (connectionDisconnectToken.CanBeCanceled) if (connectionDisconnectToken.CanBeCanceled)
{ {
@ -102,64 +84,29 @@ namespace Microsoft.Net.Http.Server
} }
} }
internal WebListener Server
{
get
{
return _server;
}
}
internal ILogger Logger
{
get { return Server.Logger; }
}
internal SafeHandle RequestQueueHandle
{
get
{
return _server.RequestQueue.Handle;
}
}
internal ulong RequestId
{
get
{
return Request.RequestId;
}
}
public unsafe Guid TraceIdentifier public unsafe Guid TraceIdentifier
{ {
get get
{ {
// This is the base GUID used by HTTP.SYS for generating the activity ID. // This is the base GUID used by HTTP.SYS for generating the activity ID.
// HTTP.SYS overwrites the first 8 bytes of the base GUID with RequestId to generate ETW activity ID. // HTTP.SYS overwrites the first 8 bytes of the base GUID with RequestId to generate ETW activity ID.
var guid = new Guid(0xffcb4c93, 0xa57f, 0x453c, 0xb6, 0x3f, 0x84, 0x71, 0xc, 0x79, 0x67, 0xbb); var guid = new Guid(0xffcb4c93, 0xa57f, 0x453c, 0xb6, 0x3f, 0x84, 0x71, 0xc, 0x79, 0x67, 0xbb);
*((ulong*)&guid) = Request.RequestId; *((ulong*)&guid) = Request.RequestId;
return guid; return guid;
} }
} }
/// <summary> public bool IsUpgradableRequest => Request.IsUpgradable;
/// The authentication challengest that will be added to the response if the status code is 401.
/// This must be a subset of the AuthenticationSchemes enabled on the server.
/// </summary>
public AuthenticationSchemes AuthenticationChallenges { get; set; }
public bool IsUpgradableRequest
{
get { return _request.IsUpgradable; }
}
public Task<Stream> UpgradeAsync() public Task<Stream> UpgradeAsync()
{ {
if (!IsUpgradableRequest || _response.HasStarted) if (!IsUpgradableRequest)
{ {
throw new InvalidOperationException("This request cannot be upgraded. It is incompatible, or the response has already started."); throw new InvalidOperationException("This request cannot be upgraded, it is incompatible.");
}
if (Response.HasStarted)
{
throw new InvalidOperationException("This request cannot be upgraded, the response has already started.");
} }
// Set the status code and reason phrase // Set the status code and reason phrase
@ -176,19 +123,22 @@ namespace Microsoft.Net.Http.Server
// TODO: Public when needed // TODO: Public when needed
internal bool TryGetChannelBinding(ref ChannelBinding value) internal bool TryGetChannelBinding(ref ChannelBinding value)
{ {
if (!Request.IsSecureConnection) if (!Request.IsHttps)
{ {
LogHelper.LogDebug(Logger, "TryGetChannelBinding", "Channel binding requires HTTPS."); LogHelper.LogDebug(Logger, "TryGetChannelBinding", "Channel binding requires HTTPS.");
return false; return false;
} }
value = ClientCertLoader.GetChannelBindingFromTls(Server.RequestQueue, Request.ConnectionId, Logger); value = ClientCertLoader.GetChannelBindingFromTls(Server.RequestQueue, Request.UConnectionId, Logger);
Debug.Assert(value != null, "GetChannelBindingFromTls returned null even though OS supposedly supports Extended Protection"); Debug.Assert(value != null, "GetChannelBindingFromTls returned null even though OS supposedly supports Extended Protection");
LogHelper.LogInfo(Logger, "Channel binding retrieved."); LogHelper.LogInfo(Logger, "Channel binding retrieved.");
return value != null; return value != null;
} }
/// <summary>
/// Flushes and completes the response.
/// </summary>
public void Dispose() public void Dispose()
{ {
if (_disposed) if (_disposed)
@ -204,14 +154,17 @@ namespace Microsoft.Net.Http.Server
{ {
_requestAbortSource.Dispose(); _requestAbortSource.Dispose();
} }
_response.Dispose(); Response.Dispose();
} }
finally finally
{ {
_request.Dispose(); Request.Dispose();
} }
} }
/// <summary>
/// Forcibly terminate and dispose the request, closing the connection if necessary.
/// </summary>
public void Abort() public void Abort()
{ {
// May be called from Dispose() code path, don't check _disposed. // May be called from Dispose() code path, don't check _disposed.
@ -229,8 +182,8 @@ namespace Microsoft.Net.Http.Server
} }
_requestAbortSource.Dispose(); _requestAbortSource.Dispose();
} }
ForceCancelRequest(RequestQueueHandle, _request.RequestId); ForceCancelRequest();
_request.Dispose(); Request.Dispose();
} }
private static void Abort(object state) private static void Abort(object state)
@ -239,30 +192,25 @@ namespace Microsoft.Net.Http.Server
context.Abort(); context.Abort();
} }
// This is only called while processing incoming requests. We don't have to worry about canceling internal CancellationTokenRegistration RegisterForCancellation(CancellationToken cancellationToken)
// any response writes.
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification =
"It is safe to ignore the return value on a cancel operation because the connection is being closed")]
internal static void CancelRequest(SafeHandle requestQueueHandle, ulong requestId)
{ {
UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(requestQueueHandle, requestId, return cancellationToken.Register(AbortDelegate, this);
IntPtr.Zero);
} }
// The request is being aborted, but large writes may be in progress. Cancel them. // The request is being aborted, but large writes may be in progress. Cancel them.
internal void ForceCancelRequest(SafeHandle requestQueueHandle, ulong requestId) internal void ForceCancelRequest()
{ {
try try
{ {
uint statusCode = UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(requestQueueHandle, requestId, var statusCode = UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(Server.RequestQueue.Handle,
IntPtr.Zero); Request.RequestId, IntPtr.Zero);
// Either the connection has already dropped, or the last write is in progress. // Either the connection has already dropped, or the last write is in progress.
// The requestId becomes invalid as soon as the last Content-Length write starts. // The requestId becomes invalid as soon as the last Content-Length write starts.
// The only way to cancel now is with CancelIoEx. // The only way to cancel now is with CancelIoEx.
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_CONNECTION_INVALID) if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_CONNECTION_INVALID)
{ {
_response.CancelLastWrite(requestQueueHandle); Response.CancelLastWrite();
} }
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)

View File

@ -26,6 +26,7 @@ using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.Net.Http.Server namespace Microsoft.Net.Http.Server
{ {
@ -48,6 +49,12 @@ namespace Microsoft.Net.Http.Server
get { return _requestContext; } get { return _requestContext; }
} }
private SafeHandle RequestQueueHandle => RequestContext.Server.RequestQueue.Handle;
private ulong RequestId => RequestContext.Request.RequestId;
private ILogger Logger => RequestContext.Server.Logger;
public override bool CanSeek public override bool CanSeek
{ {
get get
@ -173,8 +180,8 @@ namespace Microsoft.Net.Http.Server
statusCode = statusCode =
UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
flags, flags,
(IntPtr)(pBuffer + offset), (IntPtr)(pBuffer + offset),
(uint)size, (uint)size,
@ -186,7 +193,7 @@ namespace Microsoft.Net.Http.Server
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) 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 WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "Read", exception); LogHelper.LogException(Logger, "Read", exception);
Abort(); Abort();
throw exception; throw exception;
} }
@ -256,8 +263,8 @@ namespace Microsoft.Net.Http.Server
statusCode = statusCode =
UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
flags, flags,
asyncResult.PinnedBuffer, asyncResult.PinnedBuffer,
(uint)size, (uint)size,
@ -266,7 +273,7 @@ namespace Microsoft.Net.Http.Server
} }
catch (Exception e) catch (Exception e)
{ {
LogHelper.LogException(_requestContext.Logger, "BeginRead", e); LogHelper.LogException(Logger, "BeginRead", e);
asyncResult.Dispose(); asyncResult.Dispose();
throw; throw;
} }
@ -282,7 +289,7 @@ namespace Microsoft.Net.Http.Server
else else
{ {
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "BeginRead", exception); LogHelper.LogException(Logger, "BeginRead", exception);
Abort(); Abort();
throw exception; throw exception;
} }
@ -368,7 +375,7 @@ namespace Microsoft.Net.Http.Server
var cancellationRegistration = default(CancellationTokenRegistration); var cancellationRegistration = default(CancellationTokenRegistration);
if (cancellationToken.CanBeCanceled) if (cancellationToken.CanBeCanceled)
{ {
cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext); cancellationRegistration = RequestContext.RegisterForCancellation(cancellationToken);
} }
asyncResult = new RequestStreamAsyncResult(this, null, null, buffer, offset, dataRead, cancellationRegistration); asyncResult = new RequestStreamAsyncResult(this, null, null, buffer, offset, dataRead, cancellationRegistration);
@ -380,8 +387,8 @@ namespace Microsoft.Net.Http.Server
statusCode = statusCode =
UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody( UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
flags, flags,
asyncResult.PinnedBuffer, asyncResult.PinnedBuffer,
(uint)size, (uint)size,
@ -392,7 +399,7 @@ namespace Microsoft.Net.Http.Server
{ {
asyncResult.Dispose(); asyncResult.Dispose();
Abort(); Abort();
LogHelper.LogException(_requestContext.Logger, "ReadAsync", e); LogHelper.LogException(Logger, "ReadAsync", e);
throw; throw;
} }
@ -409,7 +416,7 @@ namespace Microsoft.Net.Http.Server
else else
{ {
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "ReadAsync", exception); LogHelper.LogException(Logger, "ReadAsync", exception);
Abort(); Abort();
throw exception; throw exception;
} }

View File

@ -22,14 +22,12 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -38,26 +36,26 @@ using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods;
namespace Microsoft.Net.Http.Server namespace Microsoft.Net.Http.Server
{ {
public sealed unsafe class Response public sealed class Response
{ {
private ResponseState _responseState; private ResponseState _responseState;
private HeaderCollection _headers;
private string _reasonPhrase; private string _reasonPhrase;
private ResponseStream _nativeStream; private ResponseStream _nativeStream;
private AuthenticationSchemes _authChallenges;
private TimeSpan? _cacheTtl;
private long _expectedBodyLength; private long _expectedBodyLength;
private BoundaryType _boundaryType; private BoundaryType _boundaryType;
private HttpApi.HTTP_RESPONSE_V2 _nativeResponse; private HttpApi.HTTP_RESPONSE_V2 _nativeResponse;
private IList<Tuple<Func<object, Task>, object>> _onStartingActions; private IList<Tuple<Func<object, Task>, object>> _onStartingActions;
private IList<Tuple<Func<object, Task>, object>> _onCompletedActions; private IList<Tuple<Func<object, Task>, object>> _onCompletedActions;
private RequestContext _requestContext;
private bool _bufferingEnabled; private bool _bufferingEnabled;
internal Response(RequestContext requestContext) internal Response(RequestContext requestContext)
{ {
// TODO: Verbose log // TODO: Verbose log
_requestContext = requestContext; RequestContext = requestContext;
_headers = new HeaderCollection(); Headers = new HeaderCollection();
Reset(); Reset();
} }
@ -65,14 +63,13 @@ namespace Microsoft.Net.Http.Server
{ {
if (_responseState >= ResponseState.StartedSending) if (_responseState >= ResponseState.StartedSending)
{ {
_requestContext.Abort();
throw new InvalidOperationException("The response has already been sent. Request Aborted."); throw new InvalidOperationException("The response has already been sent. Request Aborted.");
} }
// We haven't started yet, or we're just buffered, we can clear any data, headers, and state so // We haven't started yet, or we're just buffered, we can clear any data, headers, and state so
// that we can start over (e.g. to write an error message). // that we can start over (e.g. to write an error message).
_nativeResponse = new HttpApi.HTTP_RESPONSE_V2(); _nativeResponse = new HttpApi.HTTP_RESPONSE_V2();
_headers.IsReadOnly = false; Headers.IsReadOnly = false;
_headers.Clear(); Headers.Clear();
_reasonPhrase = null; _reasonPhrase = null;
_boundaryType = BoundaryType.None; _boundaryType = BoundaryType.None;
_nativeResponse.Response_V1.StatusCode = (ushort)HttpStatusCode.OK; _nativeResponse.Response_V1.StatusCode = (ushort)HttpStatusCode.OK;
@ -81,10 +78,11 @@ namespace Microsoft.Net.Http.Server
_responseState = ResponseState.Created; _responseState = ResponseState.Created;
_onStartingActions = new List<Tuple<Func<object, Task>, object>>(); _onStartingActions = new List<Tuple<Func<object, Task>, object>>();
_onCompletedActions = new List<Tuple<Func<object, Task>, object>>(); _onCompletedActions = new List<Tuple<Func<object, Task>, object>>();
_bufferingEnabled = _requestContext.Server.BufferResponses; _bufferingEnabled = RequestContext.Server.BufferResponses;
_expectedBodyLength = 0; _expectedBodyLength = 0;
_nativeStream = null; _nativeStream = null;
CacheTtl = null; _cacheTtl = null;
_authChallenges = RequestContext.Server.AuthenticationManager.AuthenticationSchemes & ~AuthenticationSchemes.AllowAnonymous;
} }
private enum ResponseState private enum ResponseState
@ -96,30 +94,19 @@ namespace Microsoft.Net.Http.Server
Closed, Closed,
} }
private RequestContext RequestContext private RequestContext RequestContext { get; }
{
get
{
return _requestContext;
}
}
private Request Request private Request Request => RequestContext.Request;
{
get
{
return RequestContext.Request;
}
}
public int StatusCode public int StatusCode
{ {
get { return _nativeResponse.Response_V1.StatusCode; } get { return _nativeResponse.Response_V1.StatusCode; }
set set
{ {
// Http.Sys automatically sends 100 Continue responses when you read from the request body.
if (value <= 100 || 999 < value) if (value <= 100 || 999 < value)
{ {
throw new ArgumentOutOfRangeException("value", value, string.Format(Resources.Exception_InvalidStatusCode, value)); throw new ArgumentOutOfRangeException(nameof(value), value, string.Format(Resources.Exception_InvalidStatusCode, value));
} }
CheckResponseStarted(); CheckResponseStarted();
_nativeResponse.Response_V1.StatusCode = (ushort)value; _nativeResponse.Response_V1.StatusCode = (ushort)value;
@ -157,26 +144,39 @@ namespace Microsoft.Net.Http.Server
} }
} }
internal string GetReasonPhrase(int statusCode) /// <summary>
/// The authentication challenges that will be added to the response if the status code is 401.
/// This must be a subset of the AuthenticationSchemes enabled on the server.
/// </summary>
public AuthenticationSchemes AuthenticationChallenges
{
get { return _authChallenges; }
set
{
CheckResponseStarted();
_authChallenges = value;
}
}
private string GetReasonPhrase(int statusCode)
{ {
string reasonPhrase = ReasonPhrase; string reasonPhrase = ReasonPhrase;
if (string.IsNullOrWhiteSpace(reasonPhrase)) if (string.IsNullOrWhiteSpace(reasonPhrase))
{ {
// if the user hasn't set this, generated on the fly, if possible. // If the user hasn't set this then it is generated on the fly if possible.
// We know this one is safe, no need to verify it as in the setter.
reasonPhrase = HttpReasonPhrase.Get(statusCode) ?? string.Empty; reasonPhrase = HttpReasonPhrase.Get(statusCode) ?? string.Empty;
} }
return reasonPhrase; return reasonPhrase;
} }
// We MUST NOT send message-body when we send responses with these Status codes // We MUST NOT send message-body when we send responses with these Status codes
private static readonly int[] NoResponseBody = { 100, 101, 204, 205, 304 }; private static readonly int[] StatusWithNoResponseBody = { 100, 101, 204, 205, 304 };
private static bool CanSendResponseBody(int responseCode) private static bool CanSendResponseBody(int responseCode)
{ {
for (int i = 0; i < NoResponseBody.Length; i++) for (int i = 0; i < StatusWithNoResponseBody.Length; i++)
{ {
if (responseCode == NoResponseBody[i]) if (responseCode == StatusWithNoResponseBody[i])
{ {
return false; return false;
} }
@ -184,10 +184,7 @@ namespace Microsoft.Net.Http.Server
return true; return true;
} }
public HeaderCollection Headers public HeaderCollection Headers { get; }
{
get { return _headers; }
}
internal long ExpectedBodyLength internal long ExpectedBodyLength
{ {
@ -261,6 +258,20 @@ namespace Microsoft.Net.Http.Server
} }
} }
/// <summary>
/// Enable kernel caching for the response with the given timeout. Http.Sys determines if the response
/// can be cached.
/// </summary>
public TimeSpan? CacheTtl
{
get { return _cacheTtl; }
set
{
CheckResponseStarted();
_cacheTtl = value;
}
}
// should only be called from RequestContext // should only be called from RequestContext
internal void Dispose() internal void Dispose()
{ {
@ -276,13 +287,17 @@ namespace Microsoft.Net.Http.Server
_responseState = ResponseState.Closed; _responseState = ResponseState.Closed;
} }
// old API, now private, and helper methods
internal BoundaryType BoundaryType internal BoundaryType BoundaryType
{ {
get { return _boundaryType; } get { return _boundaryType; }
} }
/// <summary>
/// Indicates if the response status, reason, and headers are prepared to send and can
/// no longer be modified. This is caused by the first write to the response body. However,
/// the response may not have been flushed to the network yet if the body is buffered.
/// See HasStartedSending.
/// </summary>
public bool HasStarted public bool HasStarted
{ {
get { return _responseState >= ResponseState.Started; } get { return _responseState >= ResponseState.Started; }
@ -301,13 +316,14 @@ namespace Microsoft.Net.Http.Server
get { return _responseState >= ResponseState.ComputedHeaders; } get { return _responseState >= ResponseState.ComputedHeaders; }
} }
/// <summary>
/// Indicates the initial response has been flushed to the network and can no longer be modified or Reset.
/// </summary>
public bool HasStartedSending public bool HasStartedSending
{ {
get { return _responseState >= ResponseState.StartedSending; } get { return _responseState >= ResponseState.StartedSending; }
} }
public TimeSpan? CacheTtl { get; set; }
private void EnsureResponseStream() private void EnsureResponseStream()
{ {
if (_nativeStream == null) if (_nativeStream == null)
@ -389,11 +405,10 @@ namespace Microsoft.Net.Http.Server
} }
var cachePolicy = new HttpApi.HTTP_CACHE_POLICY(); var cachePolicy = new HttpApi.HTTP_CACHE_POLICY();
var cacheTtl = CacheTtl; if (_cacheTtl.HasValue && _cacheTtl.Value > TimeSpan.Zero)
if (cacheTtl.HasValue && cacheTtl.Value > TimeSpan.Zero)
{ {
cachePolicy.Policy = HttpApi.HTTP_CACHE_POLICY_TYPE.HttpCachePolicyTimeToLive; cachePolicy.Policy = HttpApi.HTTP_CACHE_POLICY_TYPE.HttpCachePolicyTimeToLive;
cachePolicy.SecondsToLive = (uint)Math.Min(cacheTtl.Value.Ticks / TimeSpan.TicksPerSecond, Int32.MaxValue); cachePolicy.SecondsToLive = (uint)Math.Min(_cacheTtl.Value.Ticks / TimeSpan.TicksPerSecond, Int32.MaxValue);
} }
byte[] reasonPhraseBytes = HeaderEncoding.GetBytes(reasonPhrase); byte[] reasonPhraseBytes = HeaderEncoding.GetBytes(reasonPhrase);
@ -405,7 +420,7 @@ namespace Microsoft.Net.Http.Server
{ {
statusCode = statusCode =
HttpApi.HttpSendHttpResponse( HttpApi.HttpSendHttpResponse(
RequestContext.RequestQueueHandle, RequestContext.Server.RequestQueue.Handle,
Request.RequestId, Request.RequestId,
(uint)flags, (uint)flags,
pResponse, pResponse,
@ -471,7 +486,7 @@ namespace Microsoft.Net.Http.Server
var responseContentLength = ContentLength; var responseContentLength = ContentLength;
var responseCloseSet = Matches(Constants.Close, responseConnectionString); var responseCloseSet = Matches(Constants.Close, responseConnectionString);
var responseChunkedSet = Matches(Constants.Chunked, transferEncodingString); var responseChunkedSet = Matches(Constants.Chunked, transferEncodingString);
var statusCanHaveBody = CanSendResponseBody(_requestContext.Response.StatusCode); var statusCanHaveBody = CanSendResponseBody(RequestContext.Response.StatusCode);
// Determine if the connection will be kept alive or closed. // Determine if the connection will be kept alive or closed.
var keepConnectionAlive = true; var keepConnectionAlive = true;
@ -540,7 +555,7 @@ namespace Microsoft.Net.Http.Server
return string.Equals(knownValue, input?.Trim(), StringComparison.OrdinalIgnoreCase); return string.Equals(knownValue, input?.Trim(), StringComparison.OrdinalIgnoreCase);
} }
private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade) private unsafe List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
{ {
Headers.IsReadOnly = true; // Prohibit further modifications. Headers.IsReadOnly = true; // Prohibit further modifications.
HttpApi.HTTP_UNKNOWN_HEADER[] unknownHeaders = null; HttpApi.HTTP_UNKNOWN_HEADER[] unknownHeaders = null;
@ -736,12 +751,9 @@ namespace Microsoft.Net.Http.Server
} }
} }
internal void CancelLastWrite(SafeHandle requestQueueHandle) internal void CancelLastWrite()
{ {
if (_nativeStream != null) _nativeStream?.CancelLastWrite();
{
_nativeStream.CancelLastWrite(requestQueueHandle);
}
} }
public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancel) public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancel)

View File

@ -29,6 +29,7 @@ using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods; using static Microsoft.Net.Http.Server.UnsafeNclNativeMethods;
namespace Microsoft.Net.Http.Server namespace Microsoft.Net.Http.Server
@ -56,6 +57,12 @@ namespace Microsoft.Net.Http.Server
get { return _requestContext; } get { return _requestContext; }
} }
private SafeHandle RequestQueueHandle => RequestContext.Server.RequestQueue.Handle;
private ulong RequestId => RequestContext.Request.RequestId;
private ILogger Logger => RequestContext.Server.Logger;
public override bool CanSeek public override bool CanSeek
{ {
get get
@ -125,7 +132,7 @@ namespace Microsoft.Net.Http.Server
{ {
_requestContext.Abort(); _requestContext.Abort();
// This is logged rather than thrown because it is too late for an exception to be visible in user code. // This is logged rather than thrown because it is too late for an exception to be visible in user code.
LogHelper.LogError(_requestContext.Logger, "ResponseStream::Dispose", "Fewer bytes were written than were specified in the Content-Length."); LogHelper.LogError(Logger, "ResponseStream::Dispose", "Fewer bytes were written than were specified in the Content-Length.");
return; return;
} }
@ -153,8 +160,8 @@ namespace Microsoft.Net.Http.Server
fixed (HttpApi.HTTP_DATA_CHUNK* pDataChunks = dataChunks) fixed (HttpApi.HTTP_DATA_CHUNK* pDataChunks = dataChunks)
{ {
statusCode = HttpApi.HttpSendResponseEntityBody( statusCode = HttpApi.HttpSendResponseEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
(uint)flags, (uint)flags,
(ushort)dataChunks.Length, (ushort)dataChunks.Length,
pDataChunks, pDataChunks,
@ -182,7 +189,7 @@ namespace Microsoft.Net.Http.Server
&& (!endOfRequest || (statusCode != ErrorCodes.ERROR_CONNECTION_INVALID && statusCode != ErrorCodes.ERROR_INVALID_PARAMETER))) && (!endOfRequest || (statusCode != ErrorCodes.ERROR_CONNECTION_INVALID && statusCode != ErrorCodes.ERROR_INVALID_PARAMETER)))
{ {
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "Flush", exception); LogHelper.LogException(Logger, "Flush", exception);
Abort(); Abort();
throw exception; throw exception;
} }
@ -287,7 +294,7 @@ namespace Microsoft.Net.Http.Server
var cancellationRegistration = default(CancellationTokenRegistration); var cancellationRegistration = default(CancellationTokenRegistration);
if (cancellationToken.CanBeCanceled) if (cancellationToken.CanBeCanceled)
{ {
cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext); cancellationRegistration = RequestContext.RegisterForCancellation(cancellationToken);
} }
var flags = ComputeLeftToWrite(); var flags = ComputeLeftToWrite();
@ -311,8 +318,8 @@ namespace Microsoft.Net.Http.Server
else else
{ {
statusCode = HttpApi.HttpSendResponseEntityBody( statusCode = HttpApi.HttpSendResponseEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
(uint)flags, (uint)flags,
asyncResult.DataChunkCount, asyncResult.DataChunkCount,
asyncResult.DataChunks, asyncResult.DataChunks,
@ -325,7 +332,7 @@ namespace Microsoft.Net.Http.Server
} }
catch (Exception e) catch (Exception e)
{ {
LogHelper.LogException(_requestContext.Logger, "FlushAsync", e); LogHelper.LogException(Logger, "FlushAsync", e);
asyncResult.Dispose(); asyncResult.Dispose();
Abort(); Abort();
throw; throw;
@ -341,7 +348,7 @@ namespace Microsoft.Net.Http.Server
else else
{ {
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "FlushAsync", exception); LogHelper.LogException(Logger, "FlushAsync", exception);
Abort(); Abort();
throw exception; throw exception;
} }
@ -408,8 +415,7 @@ namespace Microsoft.Net.Http.Server
} }
if (_leftToWrite == long.MinValue) if (_leftToWrite == long.MinValue)
{ {
UnsafeNclNativeMethods.HttpApi.HTTP_VERB method = _requestContext.Request.GetKnownMethod(); if (_requestContext.Request.IsHeadMethod)
if (method == UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD)
{ {
_leftToWrite = 0; _leftToWrite = 0;
} }
@ -578,7 +584,7 @@ namespace Microsoft.Net.Http.Server
var cancellationRegistration = default(CancellationTokenRegistration); var cancellationRegistration = default(CancellationTokenRegistration);
if (cancellationToken.CanBeCanceled) if (cancellationToken.CanBeCanceled)
{ {
cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext); cancellationRegistration = RequestContext.RegisterForCancellation(cancellationToken);
} }
uint statusCode; uint statusCode;
@ -615,8 +621,8 @@ namespace Microsoft.Net.Http.Server
{ {
// TODO: If opaque then include the buffer data flag. // TODO: If opaque then include the buffer data flag.
statusCode = HttpApi.HttpSendResponseEntityBody( statusCode = HttpApi.HttpSendResponseEntityBody(
_requestContext.RequestQueueHandle, RequestQueueHandle,
_requestContext.RequestId, RequestId,
(uint)flags, (uint)flags,
asyncResult.DataChunkCount, asyncResult.DataChunkCount,
asyncResult.DataChunks, asyncResult.DataChunks,
@ -629,7 +635,7 @@ namespace Microsoft.Net.Http.Server
} }
catch (Exception e) catch (Exception e)
{ {
LogHelper.LogException(_requestContext.Logger, "SendFileAsync", e); LogHelper.LogException(Logger, "SendFileAsync", e);
asyncResult.Dispose(); asyncResult.Dispose();
Abort(); Abort();
throw; throw;
@ -645,7 +651,7 @@ namespace Microsoft.Net.Http.Server
else else
{ {
Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode)); Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
LogHelper.LogException(_requestContext.Logger, "SendFileAsync", exception); LogHelper.LogException(Logger, "SendFileAsync", exception);
Abort(); Abort();
throw exception; throw exception;
} }
@ -713,12 +719,12 @@ namespace Microsoft.Net.Http.Server
// Sync can only be Canceled by CancelSynchronousIo, but we don't attempt this right now. // Sync can only be Canceled by CancelSynchronousIo, but we don't attempt this right now.
[SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification = [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", Justification =
"It is safe to ignore the return value on a cancel operation because the connection is being closed")] "It is safe to ignore the return value on a cancel operation because the connection is being closed")]
internal unsafe void CancelLastWrite(SafeHandle requestQueueHandle) internal unsafe void CancelLastWrite()
{ {
ResponseStreamAsyncResult asyncState = _lastWrite; ResponseStreamAsyncResult asyncState = _lastWrite;
if (asyncState != null && !asyncState.IsCompleted) if (asyncState != null && !asyncState.IsCompleted)
{ {
UnsafeNclNativeMethods.CancelIoEx(requestQueueHandle, asyncState.NativeOverlapped); UnsafeNclNativeMethods.CancelIoEx(RequestQueueHandle, asyncState.NativeOverlapped);
} }
} }

View File

@ -22,7 +22,6 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Microsoft.Net.Http.Server namespace Microsoft.Net.Http.Server
@ -53,8 +52,6 @@ namespace Microsoft.Net.Http.Server
// //
// No initialization is required because a value of zero indicates that system defaults should be used. // No initialization is required because a value of zero indicates that system defaults should be used.
_timeouts = new int[5]; _timeouts = new int[5];
LoadConfigurationSettings();
} }
#region Properties #region Properties
@ -72,11 +69,11 @@ namespace Microsoft.Net.Http.Server
{ {
get get
{ {
return GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody); return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody);
} }
set set
{ {
SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody, value); SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.EntityBody, value);
} }
} }
@ -95,11 +92,11 @@ namespace Microsoft.Net.Http.Server
{ {
get get
{ {
return GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody); return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody);
} }
set set
{ {
SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody, value); SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody, value);
} }
} }
@ -113,11 +110,11 @@ namespace Microsoft.Net.Http.Server
{ {
get get
{ {
return GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue); return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue);
} }
set set
{ {
SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue, value); SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue, value);
} }
} }
@ -132,11 +129,11 @@ namespace Microsoft.Net.Http.Server
{ {
get get
{ {
return GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection); return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection);
} }
set set
{ {
SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection, value); SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection, value);
} }
} }
@ -152,17 +149,19 @@ namespace Microsoft.Net.Http.Server
{ {
get get
{ {
return GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait); return GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait);
} }
set set
{ {
SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait, value); SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait, value);
} }
} }
/// <summary> /// <summary>
/// The minimum send rate, in bytes-per-second, for the response. The default response send rate is 150 /// The minimum send rate, in bytes-per-second, for the response. The default response send rate is 150
/// bytes-per-second. /// bytes-per-second.
///
/// Use 0 to indicate that system defaults should be used.
/// ///
/// To disable this timer set it to UInt32.MaxValue /// To disable this timer set it to UInt32.MaxValue
/// </summary> /// </summary>
@ -181,60 +180,27 @@ namespace Microsoft.Net.Http.Server
throw new ArgumentOutOfRangeException("value"); throw new ArgumentOutOfRangeException("value");
} }
SetServerTimeout(_timeouts, (uint)value); SetServerTimeouts(_timeouts, (uint)value);
_minSendBytesPerSecond = (uint)value; _minSendBytesPerSecond = (uint)value;
} }
} }
#endregion Properties #endregion Properties
// Initial values come from the config. The values can then be overridden using this public API.
private void LoadConfigurationSettings()
{
long[] configTimeouts = new long[_timeouts.Length + 1]; // SettingsSectionInternal.Section.HttpListenerTimeouts;
Debug.Assert(configTimeouts != null);
Debug.Assert(configTimeouts.Length == (_timeouts.Length + 1));
bool setNonDefaults = false;
for (int i = 0; i < _timeouts.Length; i++)
{
if (configTimeouts[i] != 0)
{
Debug.Assert(configTimeouts[i] <= ushort.MaxValue, "Timeout out of range: " + configTimeouts[i]);
_timeouts[i] = (int)configTimeouts[i];
setNonDefaults = true;
}
}
if (configTimeouts[5] != 0)
{
Debug.Assert(configTimeouts[5] <= uint.MaxValue, "Timeout out of range: " + configTimeouts[5]);
_minSendBytesPerSecond = (uint)configTimeouts[5];
setNonDefaults = true;
}
if (setNonDefaults)
{
SetServerTimeout(_timeouts, _minSendBytesPerSecond);
}
}
#region Helpers #region Helpers
private TimeSpan GetTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type) private TimeSpan GetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type)
{ {
// Since we maintain local state, GET is local. // Since we maintain local state, GET is local.
return new TimeSpan(0, 0, (int)_timeouts[(int)type]); return new TimeSpan(0, 0, (int)_timeouts[(int)type]);
} }
private void SetTimespanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type, TimeSpan value) private void SetTimeSpanTimeout(UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE type, TimeSpan value)
{ {
Int64 timeoutValue;
// All timeouts are defined as USHORT in native layer (except MinSendRate, which is ULONG). Make sure that // All timeouts are defined as USHORT in native layer (except MinSendRate, which is ULONG). Make sure that
// timeout value is within range. // timeout value is within range.
timeoutValue = Convert.ToInt64(value.TotalSeconds); var timeoutValue = Convert.ToInt64(value.TotalSeconds);
if (timeoutValue < 0 || timeoutValue > ushort.MaxValue) if (timeoutValue < 0 || timeoutValue > ushort.MaxValue)
{ {
@ -243,17 +209,15 @@ namespace Microsoft.Net.Http.Server
// Use local state to get values for other timeouts. Call into the native layer and if that // Use local state to get values for other timeouts. Call into the native layer and if that
// call succeeds, update local state. // call succeeds, update local state.
var newTimeouts = (int[])_timeouts.Clone();
int[] currentTimeouts = _timeouts; newTimeouts[(int)type] = (int)timeoutValue;
currentTimeouts[(int)type] = (int)timeoutValue; SetServerTimeouts(newTimeouts, _minSendBytesPerSecond);
SetServerTimeout(currentTimeouts, _minSendBytesPerSecond);
_timeouts[(int)type] = (int)timeoutValue; _timeouts[(int)type] = (int)timeoutValue;
} }
private unsafe void SetServerTimeout(int[] timeouts, uint minSendBytesPerSecond) private unsafe void SetServerTimeouts(int[] timeouts, uint minSendBytesPerSecond)
{ {
UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_LIMIT_INFO timeoutinfo = var timeoutinfo = new UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_LIMIT_INFO();
new UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_LIMIT_INFO();
timeoutinfo.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT; timeoutinfo.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
timeoutinfo.DrainEntityBody = timeoutinfo.DrainEntityBody =
@ -268,7 +232,7 @@ namespace Microsoft.Net.Http.Server
(ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait]; (ushort)timeouts[(int)UnsafeNclNativeMethods.HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait];
timeoutinfo.MinSendRate = minSendBytesPerSecond; timeoutinfo.MinSendRate = minSendBytesPerSecond;
IntPtr infoptr = new IntPtr(&timeoutinfo); var infoptr = new IntPtr(&timeoutinfo);
_server.UrlGroup.SetProperty( _server.UrlGroup.SetProperty(
UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty, UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty,

View File

@ -138,17 +138,6 @@ namespace Microsoft.Net.Http.Server
get { return _logger; } get { return _logger; }
} }
public UrlPrefixCollection UrlPrefixes
{
get { return _urlPrefixes; }
}
public bool BufferResponses
{
get { return _bufferResponses; }
set { _bufferResponses = value; }
}
internal UrlGroup UrlGroup internal UrlGroup UrlGroup
{ {
get { return _urlGroup; } get { return _urlGroup; }
@ -164,29 +153,7 @@ namespace Microsoft.Net.Http.Server
get { return _disconnectListener; } get { return _disconnectListener; }
} }
/// <summary> // TODO: https://github.com/aspnet/WebListener/issues/173
/// Exposes the Http.Sys timeout configurations. These may also be configured in the registry.
/// </summary>
public TimeoutManager TimeoutManager
{
get { return _timeoutManager; }
}
public AuthenticationManager AuthenticationManager
{
get { return _authManager; }
}
internal static bool IsSupported
{
get { return UnsafeNclNativeMethods.HttpApi.Supported; }
}
public bool IsListening
{
get { return _state == State.Started; }
}
internal bool IgnoreWriteExceptions internal bool IgnoreWriteExceptions
{ {
get { return _ignoreWriteExceptions; } get { return _ignoreWriteExceptions; }
@ -197,6 +164,38 @@ namespace Microsoft.Net.Http.Server
} }
} }
public UrlPrefixCollection UrlPrefixes
{
get { return _urlPrefixes; }
}
public bool BufferResponses
{
get { return _bufferResponses; }
set { _bufferResponses = value; }
}
/// <summary>
/// Exposes the Http.Sys timeout configurations. These may also be configured in the registry.
/// </summary>
public TimeoutManager TimeoutManager
{
get { return _timeoutManager; }
}
/// <summary>
/// Http.Sys authentication settings.
/// </summary>
public AuthenticationManager AuthenticationManager
{
get { return _authManager; }
}
public bool IsListening
{
get { return _state == State.Started; }
}
/// <summary> /// <summary>
/// Sets the maximum number of requests that will be queued up in Http.Sys. /// Sets the maximum number of requests that will be queued up in Http.Sys.
/// </summary> /// </summary>
@ -208,6 +207,8 @@ namespace Microsoft.Net.Http.Server
{ {
throw new ArgumentOutOfRangeException("limit", limit, string.Empty); throw new ArgumentOutOfRangeException("limit", limit, string.Empty);
} }
// Don't try to change it if the new limit is the same
if ((!_requestQueueLength.HasValue && limit == DefaultRequestQueueLength) if ((!_requestQueueLength.HasValue && limit == DefaultRequestQueueLength)
|| (_requestQueueLength.HasValue && limit == _requestQueueLength.Value)) || (_requestQueueLength.HasValue && limit == _requestQueueLength.Value))
{ {
@ -218,6 +219,9 @@ namespace Microsoft.Net.Http.Server
_requestQueue.SetLengthLimit(_requestQueueLength.Value); _requestQueue.SetLengthLimit(_requestQueueLength.Value);
} }
/// <summary>
/// Start accepting incoming requests.
/// </summary>
public void Start() public void Start()
{ {
CheckDisposed(); CheckDisposed();
@ -298,7 +302,6 @@ namespace Microsoft.Net.Http.Server
Dispose(true); Dispose(true);
} }
// old API, now private, and helper methods
private void Dispose(bool disposing) private void Dispose(bool disposing)
{ {
if (!disposing) if (!disposing)
@ -350,31 +353,10 @@ namespace Microsoft.Net.Http.Server
_serverSession.Dispose(); _serverSession.Dispose();
} }
internal unsafe bool ValidateRequest(NativeRequestContext requestMemory) /// <summary>
{ /// Accept a request from the incoming request queue.
// Block potential DOS attacks /// </summary>
if (requestMemory.RequestBlob->Headers.UnknownHeaderCount > UnknownHeaderLimit) public Task<RequestContext> AcceptAsync()
{
SendError(requestMemory.RequestBlob->RequestId, HttpStatusCode.BadRequest, authChallenges: null);
return false;
}
return true;
}
internal unsafe bool ValidateAuth(NativeRequestContext requestMemory)
{
var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)requestMemory.RequestBlob;
if (!AuthenticationManager.AllowAnonymous && !AuthenticationManager.CheckAuthenticated(requestV2->pRequestInfo))
{
SendError(requestMemory.RequestBlob->RequestId, HttpStatusCode.Unauthorized,
AuthenticationManager.GenerateChallenges(AuthenticationManager.AuthenticationSchemes));
return false;
}
return true;
}
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by callback")]
public Task<RequestContext> GetContextAsync()
{ {
AsyncAcceptContext asyncResult = null; AsyncAcceptContext asyncResult = null;
try try
@ -404,6 +386,29 @@ namespace Microsoft.Net.Http.Server
return asyncResult.Task; return asyncResult.Task;
} }
internal unsafe bool ValidateRequest(NativeRequestContext requestMemory)
{
// Block potential DOS attacks
if (requestMemory.RequestBlob->Headers.UnknownHeaderCount > UnknownHeaderLimit)
{
SendError(requestMemory.RequestBlob->RequestId, HttpStatusCode.BadRequest, authChallenges: null);
return false;
}
return true;
}
internal unsafe bool ValidateAuth(NativeRequestContext requestMemory)
{
var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)requestMemory.RequestBlob;
if (!AuthenticationManager.AllowAnonymous && !AuthenticationManager.CheckAuthenticated(requestV2->pRequestInfo))
{
SendError(requestMemory.RequestBlob->RequestId, HttpStatusCode.Unauthorized,
AuthenticationManager.GenerateChallenges(AuthenticationManager.AuthenticationSchemes));
return false;
}
return true;
}
private unsafe void SendError(ulong requestId, HttpStatusCode httpStatusCode, IList<string> authChallenges) private unsafe void SendError(ulong requestId, HttpStatusCode httpStatusCode, IList<string> authChallenges)
{ {
UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2 httpResponse = new UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2(); UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2 httpResponse = new UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2();
@ -494,7 +499,7 @@ namespace Microsoft.Net.Http.Server
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{ {
// if we fail to send a 401 something's seriously wrong, abort the request // if we fail to send a 401 something's seriously wrong, abort the request
RequestContext.CancelRequest(_requestQueue.Handle, requestId); UnsafeNclNativeMethods.HttpApi.HttpCancelHttpRequest(_requestQueue.Handle, requestId, IntPtr.Zero);
} }
} }
finally finally

View File

@ -1,4 +1,8 @@
{ {
"buildOptions": {
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk"
},
"testRunner": "xunit", "testRunner": "xunit",
"dependencies": { "dependencies": {
"dotnet-test-xunit": "2.2.0-*", "dotnet-test-xunit": "2.2.0-*",

View File

@ -25,16 +25,16 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.False(context.User.Identity.IsAuthenticated); Assert.False(context.User.Identity.IsAuthenticated);
if (authType == AuthenticationSchemes.AllowAnonymous) if (authType == AuthenticationSchemes.AllowAnonymous)
{ {
Assert.Equal(AuthenticationSchemes.None, context.AuthenticationChallenges); Assert.Equal(AuthenticationSchemes.None, context.Response.AuthenticationChallenges);
} }
else else
{ {
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
} }
context.Dispose(); context.Dispose();
@ -57,7 +57,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var contextTask = server.GetContextAsync(); // Fails when the server shuts down, the challenge happens internally. var contextTask = server.AcceptAsync(); // Fails when the server shuts down, the challenge happens internally.
var response = await responseTask; var response = await responseTask;
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase);
@ -77,10 +77,10 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.False(context.User.Identity.IsAuthenticated); Assert.False(context.User.Identity.IsAuthenticated);
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
context.Dispose(); context.Dispose();
@ -104,10 +104,10 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.False(context.User.Identity.IsAuthenticated); Assert.False(context.User.Identity.IsAuthenticated);
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
context.Dispose(); context.Dispose();
@ -130,17 +130,17 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.False(context.User.Identity.IsAuthenticated); Assert.False(context.User.Identity.IsAuthenticated);
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
context.Dispose(); context.Dispose();
context = await server.GetContextAsync(); context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.True(context.User.Identity.IsAuthenticated); Assert.True(context.User.Identity.IsAuthenticated);
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
context.Dispose(); context.Dispose();
var response = await responseTask; var response = await responseTask;
@ -161,10 +161,10 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.True(context.User.Identity.IsAuthenticated); Assert.True(context.User.Identity.IsAuthenticated);
Assert.Equal(authType, context.AuthenticationChallenges); Assert.Equal(authType, context.Response.AuthenticationChallenges);
context.Dispose(); context.Dispose();
var response = await responseTask; var response = await responseTask;
@ -181,10 +181,10 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.True(context.User.Identity.IsAuthenticated); Assert.True(context.User.Identity.IsAuthenticated);
Assert.Equal(AuthenticationSchemes.Kerberos, context.AuthenticationChallenges); Assert.Equal(AuthenticationSchemes.Kerberos, context.Response.AuthenticationChallenges);
context.Dispose(); context.Dispose();
var response = await responseTask; var response = await responseTask;
@ -201,10 +201,10 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.NotNull(context.User); Assert.NotNull(context.User);
Assert.False(context.User.Identity.IsAuthenticated); Assert.False(context.User.Identity.IsAuthenticated);
Assert.Equal(AuthenticationSchemes.Kerberos, context.AuthenticationChallenges); Assert.Equal(AuthenticationSchemes.Kerberos, context.Response.AuthenticationChallenges);
context.Response.StatusCode = 401; context.Response.StatusCode = 401;
context.Dispose(); context.Dispose();

View File

@ -21,7 +21,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(Address); Task<string> responseTask = SendRequestAsync(Address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
string response = await responseTask; string response = await responseTask;
@ -36,7 +36,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(Address); Task<string> responseTask = SendRequestAsync(Address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] body = Encoding.UTF8.GetBytes("Hello World"); byte[] body = Encoding.UTF8.GetBytes("Hello World");
context.Response.ContentLength = body.Length; context.Response.ContentLength = body.Length;
await context.Response.Body.WriteAsync(body, 0, body.Length); await context.Response.Body.WriteAsync(body, 0, body.Length);
@ -54,7 +54,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(Address, "Hello World"); Task<string> responseTask = SendRequestAsync(Address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
string input = new StreamReader(context.Request.Body).ReadToEnd(); string input = new StreamReader(context.Request.Body).ReadToEnd();
Assert.Equal("Hello World", input); Assert.Equal("Hello World", input);
context.Response.ContentLength = 11; context.Response.ContentLength = 11;
@ -75,7 +75,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(Address); Task<string> responseTask = SendRequestAsync(Address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cert = await context.Request.GetClientCertificateAsync(); var cert = await context.Request.GetClientCertificateAsync();
Assert.Null(cert); Assert.Null(cert);
context.Dispose(); context.Dispose();
@ -94,7 +94,7 @@ namespace Microsoft.Net.Http.Server
Assert.NotNull(clientCert); Assert.NotNull(clientCert);
Task<string> responseTask = SendRequestAsync(Address, clientCert); Task<string> responseTask = SendRequestAsync(Address, clientCert);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cert = await context.Request.GetClientCertificateAsync(); var cert = await context.Request.GetClientCertificateAsync();
Assert.NotNull(cert); Assert.NotNull(cert);
context.Dispose(); context.Dispose();

View File

@ -22,7 +22,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> clientTask = SendRequestAsync(address); Task<HttpResponseMessage> clientTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] body = Encoding.UTF8.GetBytes("Hello World"); byte[] body = Encoding.UTF8.GetBytes("Hello World");
context.Response.Body.Write(body, 0, body.Length); context.Response.Body.Write(body, 0, body.Length);
@ -44,7 +44,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<Stream> clientTask = SendOpaqueRequestAsync("GET", address); Task<Stream> clientTask = SendOpaqueRequestAsync("GET", address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.True(context.IsUpgradableRequest); Assert.True(context.IsUpgradableRequest);
context.Response.Headers["Upgrade"] = "WebSocket"; // Win8.1 blocks anything but WebSocket context.Response.Headers["Upgrade"] = "WebSocket"; // Win8.1 blocks anything but WebSocket
Stream serverStream = await context.UpgradeAsync(); Stream serverStream = await context.UpgradeAsync();
@ -88,7 +88,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<Stream> clientTask = SendOpaqueRequestAsync(method, address, extraHeader); Task<Stream> clientTask = SendOpaqueRequestAsync(method, address, extraHeader);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.True(context.IsUpgradableRequest); Assert.True(context.IsUpgradableRequest);
context.Response.Headers["Upgrade"] = "WebSocket"; // Win8.1 blocks anything but WebSocket context.Response.Headers["Upgrade"] = "WebSocket"; // Win8.1 blocks anything but WebSocket
Stream serverStream = await context.UpgradeAsync(); Stream serverStream = await context.UpgradeAsync();
@ -128,7 +128,7 @@ namespace Microsoft.Net.Http.Server
using (var server = Utilities.CreateHttpServer(out address)) using (var server = Utilities.CreateHttpServer(out address))
{ {
var clientTask = SendOpaqueRequestAsync(method, address, extraHeader); var clientTask = SendOpaqueRequestAsync(method, address, extraHeader);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.False(context.IsUpgradableRequest); Assert.False(context.IsUpgradableRequest);
context.Dispose(); context.Dispose();

View File

@ -22,7 +22,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, "Hello World"); Task<string> responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[100]; byte[] input = new byte[100];
int read = context.Request.Body.Read(input, 0, input.Length); int read = context.Request.Body.Read(input, 0, input.Length);
context.Response.ContentLength = read; context.Response.ContentLength = read;
@ -41,7 +41,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, "Hello World"); Task<string> responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[100]; byte[] input = new byte[100];
int read = await context.Request.Body.ReadAsync(input, 0, input.Length); int read = await context.Request.Body.ReadAsync(input, 0, input.Length);
context.Response.ContentLength = read; context.Response.ContentLength = read;
@ -60,7 +60,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, "Hello World"); Task<string> responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[100]; byte[] input = new byte[100];
int read = context.Request.Body.EndRead(context.Request.Body.BeginRead(input, 0, input.Length, null, null)); int read = context.Request.Body.EndRead(context.Request.Body.BeginRead(input, 0, input.Length, null, null));
context.Response.ContentLength = read; context.Response.ContentLength = read;
@ -80,7 +80,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, "Hello World"); Task<string> responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[100]; byte[] input = new byte[100];
Assert.Throws<ArgumentNullException>("buffer", () => context.Request.Body.Read(null, 0, 1)); Assert.Throws<ArgumentNullException>("buffer", () => context.Request.Body.Read(null, 0, 1));
Assert.Throws<ArgumentOutOfRangeException>("offset", () => context.Request.Body.Read(input, -1, 1)); Assert.Throws<ArgumentOutOfRangeException>("offset", () => context.Request.Body.Read(input, -1, 1));
@ -105,7 +105,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
int read = context.Request.Body.Read(input, 0, input.Length); int read = context.Request.Body.Read(input, 0, input.Length);
Assert.Equal(5, read); Assert.Equal(5, read);
@ -128,7 +128,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
int read = await context.Request.Body.ReadAsync(input, 0, input.Length); int read = await context.Request.Body.ReadAsync(input, 0, input.Length);
Assert.Equal(5, read); Assert.Equal(5, read);
@ -150,7 +150,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendSocketRequestAsync(address); Task<string> responseTask = SendSocketRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[11]; byte[] input = new byte[11];
int read = await context.Request.Body.ReadAsync(input, 0, input.Length); int read = await context.Request.Body.ReadAsync(input, 0, input.Length);
Assert.Equal(10, read); Assert.Equal(10, read);
@ -176,7 +176,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, "Hello World"); Task<string> responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
@ -201,7 +201,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token); int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token);
@ -225,7 +225,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5)); cts.CancelAfter(TimeSpan.FromSeconds(5));
@ -250,7 +250,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token); int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token);
@ -275,7 +275,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address, content); Task<string> responseTask = SendRequestAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token); int read = await context.Request.Body.ReadAsync(input, 0, input.Length, cts.Token);
@ -303,7 +303,7 @@ namespace Microsoft.Net.Http.Server
var client = new HttpClient(); var client = new HttpClient();
var responseTask = client.PostAsync(address, content); var responseTask = client.PostAsync(address, content);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] input = new byte[10]; byte[] input = new byte[10];
int read = await context.Request.Body.ReadAsync(input, 0, input.Length, context.DisconnectToken); int read = await context.Request.Body.ReadAsync(input, 0, input.Length, context.DisconnectToken);
Assert.False(context.DisconnectToken.IsCancellationRequested); Assert.False(context.DisconnectToken.IsCancellationRequested);

View File

@ -20,7 +20,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address); Task<string> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var requestHeaders = context.Request.Headers; var requestHeaders = context.Request.Headers;
// NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point. // NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point.
// Assert.Equal(2, requestHeaders.Count); // Assert.Equal(2, requestHeaders.Count);
@ -46,7 +46,7 @@ namespace Microsoft.Net.Http.Server
string[] customValues = new string[] { "custom1, and custom2", "custom3" }; string[] customValues = new string[] { "custom1, and custom2", "custom3" };
Task responseTask = SendRequestAsync(address, "Custom-Header", customValues); Task responseTask = SendRequestAsync(address, "Custom-Header", customValues);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var requestHeaders = context.Request.Headers; var requestHeaders = context.Request.Headers;
Assert.Equal(4, requestHeaders.Count); Assert.Equal(4, requestHeaders.Count);
Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]);
@ -73,7 +73,7 @@ namespace Microsoft.Net.Http.Server
string[] customValues = new string[] { "custom1, and custom测试2", "custom3" }; string[] customValues = new string[] { "custom1, and custom测试2", "custom3" };
Task responseTask = SendRequestAsync(address, "Custom-Header", customValues); Task responseTask = SendRequestAsync(address, "Custom-Header", customValues);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var requestHeaders = context.Request.Headers; var requestHeaders = context.Request.Headers;
Assert.Equal(4, requestHeaders.Count); Assert.Equal(4, requestHeaders.Count);
Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]);

View File

@ -20,7 +20,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(root + "/basepath/SomePath?SomeQuery"); Task<string> responseTask = SendRequestAsync(root + "/basepath/SomePath?SomeQuery");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
// General fields // General fields
var request = context.Request; var request = context.Request;
@ -64,7 +64,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(root + requestPath); Task<string> responseTask = SendRequestAsync(root + requestPath);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
// General fields // General fields
var request = context.Request; var request = context.Request;
@ -92,7 +92,7 @@ namespace Microsoft.Net.Http.Server
using (var server = Utilities.CreateHttpServerReturnRoot("/", out root)) using (var server = Utilities.CreateHttpServerReturnRoot("/", out root))
{ {
var responseTask = SendSocketRequestAsync(root, requestPath); var responseTask = SendSocketRequestAsync(root, requestPath);
var contextTask = server.GetContextAsync(); var contextTask = server.AcceptAsync();
var response = await responseTask; var response = await responseTask;
var responseStatusCode = response.Substring(9); // Skip "HTTP/1.1 " var responseStatusCode = response.Substring(9); // Skip "HTTP/1.1 "
Assert.Equal("400", responseStatusCode); Assert.Equal("400", responseStatusCode);
@ -106,7 +106,7 @@ namespace Microsoft.Net.Http.Server
using (var server = Utilities.CreateHttpServerReturnRoot("/", out root)) using (var server = Utilities.CreateHttpServerReturnRoot("/", out root))
{ {
var responseTask = SendSocketRequestAsync(root, "/%252F"); var responseTask = SendSocketRequestAsync(root, "/%252F");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Equal("/%2F", context.Request.Path); Assert.Equal("/%2F", context.Request.Path);
} }
} }
@ -142,7 +142,7 @@ namespace Microsoft.Net.Http.Server
Task<string> responseTask = SendRequestAsync(root + requestUri); Task<string> responseTask = SendRequestAsync(root + requestUri);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var request = context.Request; var request = context.Request;
Assert.Equal(expectedPath, request.Path); Assert.Equal(expectedPath, request.Path);

View File

@ -23,7 +23,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ShouldBuffer = true; context.Response.ShouldBuffer = true;
context.Response.Body.Write(new byte[10], 0, 10); context.Response.Body.Write(new byte[10], 0, 10);
await context.Response.Body.WriteAsync(new byte[10], 0, 10); await context.Response.Body.WriteAsync(new byte[10], 0, 10);
@ -47,7 +47,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ShouldBuffer = false; context.Response.ShouldBuffer = false;
context.Response.Body.Write(new byte[10], 0, 10); context.Response.Body.Write(new byte[10], 0, 10);
await context.Response.Body.WriteAsync(new byte[10], 0, 10); await context.Response.Body.WriteAsync(new byte[10], 0, 10);
@ -71,7 +71,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Body.Write(new byte[10], 0, 10); context.Response.Body.Write(new byte[10], 0, 10);
context.Response.Body.Flush(); context.Response.Body.Flush();
await context.Response.Body.WriteAsync(new byte[10], 0, 10); await context.Response.Body.WriteAsync(new byte[10], 0, 10);
@ -94,7 +94,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["transfeR-Encoding"] = "CHunked"; context.Response.Headers["transfeR-Encoding"] = "CHunked";
Stream stream = context.Response.Body; Stream stream = context.Response.Body;
var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n"); var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n");
@ -119,7 +119,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 30 "; context.Response.Headers["Content-lenGth"] = " 30 ";
Stream stream = context.Response.Body; Stream stream = context.Response.Body;
#if NET451 #if NET451
@ -150,12 +150,12 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 20 "; context.Response.Headers["Content-lenGth"] = " 20 ";
context.Dispose(); context.Dispose();
#if !NETCOREAPP1_0 #if !NETCOREAPP1_0
// HttpClient retries the request because it didn't get a response. // HttpClient retries the request because it didn't get a response.
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 20 "; context.Response.Headers["Content-lenGth"] = " 20 ";
context.Dispose(); context.Dispose();
#endif #endif
@ -171,13 +171,13 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 20 "; context.Response.Headers["Content-lenGth"] = " 20 ";
context.Response.Body.Write(new byte[5], 0, 5); context.Response.Body.Write(new byte[5], 0, 5);
context.Dispose(); context.Dispose();
#if !NETCOREAPP1_0 #if !NETCOREAPP1_0
// HttpClient retries the request because it didn't get a response. // HttpClient retries the request because it didn't get a response.
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 20 "; context.Response.Headers["Content-lenGth"] = " 20 ";
context.Response.Body.Write(new byte[5], 0, 5); context.Response.Body.Write(new byte[5], 0, 5);
context.Dispose(); context.Dispose();
@ -194,14 +194,14 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 10 "; context.Response.Headers["Content-lenGth"] = " 10 ";
context.Response.Body.Write(new byte[5], 0, 5); context.Response.Body.Write(new byte[5], 0, 5);
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[6], 0, 6)); Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[6], 0, 6));
context.Dispose(); context.Dispose();
#if !NETCOREAPP1_0 #if !NETCOREAPP1_0
// HttpClient retries the request because it didn't get a response. // HttpClient retries the request because it didn't get a response.
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 10 "; context.Response.Headers["Content-lenGth"] = " 10 ";
context.Response.Body.Write(new byte[5], 0, 5); context.Response.Body.Write(new byte[5], 0, 5);
Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[6], 0, 6)); Assert.Throws<InvalidOperationException>(() => context.Response.Body.Write(new byte[6], 0, 6));
@ -219,7 +219,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = " 10 "; context.Response.Headers["Content-lenGth"] = " 10 ";
context.Response.Body.Write(new byte[10], 0, 10); context.Response.Body.Write(new byte[10], 0, 10);
Assert.Throws<ObjectDisposedException>(() => context.Response.Body.Write(new byte[6], 0, 6)); Assert.Throws<ObjectDisposedException>(() => context.Response.Body.Write(new byte[6], 0, 6));
@ -244,7 +244,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Body.Write(new byte[10], 0, 0); context.Response.Body.Write(new byte[10], 0, 0);
Assert.True(context.Response.HasStarted); Assert.True(context.Response.HasStarted);
await context.Response.Body.WriteAsync(new byte[10], 0, 0); await context.Response.Body.WriteAsync(new byte[10], 0, 0);
@ -268,7 +268,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ShouldBuffer = true; context.Response.ShouldBuffer = true;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@ -299,7 +299,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ShouldBuffer = true; context.Response.ShouldBuffer = true;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@ -330,7 +330,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
// First write sends headers // First write sends headers
await context.Response.Body.WriteAsync(new byte[10], 0, 10, cts.Token); await context.Response.Body.WriteAsync(new byte[10], 0, 10, cts.Token);
@ -351,7 +351,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(1)); cts.CancelAfter(TimeSpan.FromSeconds(1));
// First write sends headers // First write sends headers
@ -373,7 +373,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.Cancel(); cts.Cancel();
// First write sends headers // First write sends headers
@ -395,7 +395,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
// First write sends headers // First write sends headers
await context.Response.Body.WriteAsync(new byte[10], 0, 10, cts.Token); await context.Response.Body.WriteAsync(new byte[10], 0, 10, cts.Token);

View File

@ -30,7 +30,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -43,7 +43,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -64,7 +64,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -93,7 +93,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -124,7 +124,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.Headers["age"] = "12345"; context.Response.Headers["age"] = "12345";
@ -156,7 +156,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(0); context.Response.CacheTtl = TimeSpan.FromSeconds(0);
@ -169,7 +169,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -190,7 +190,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromMilliseconds(900); context.Response.CacheTtl = TimeSpan.FromMilliseconds(900);
@ -203,7 +203,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -224,7 +224,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(-10); context.Response.CacheTtl = TimeSpan.FromSeconds(-10);
@ -237,7 +237,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -258,7 +258,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.MaxValue; context.Response.CacheTtl = TimeSpan.MaxValue;
@ -285,7 +285,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -315,7 +315,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -329,7 +329,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Dispose(); context.Dispose();
@ -348,7 +348,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -363,7 +363,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Dispose(); context.Dispose();
@ -382,7 +382,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength = 10; context.Response.ContentLength = 10;
@ -411,7 +411,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -425,7 +425,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Dispose(); context.Dispose();
@ -444,7 +444,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength =_fileLength; context.Response.ContentLength =_fileLength;
@ -482,7 +482,7 @@ namespace Microsoft.Net.Http.Server
var responseTask = SendRequestAsync(address + status); var responseTask = SendRequestAsync(address + status);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = status; context.Response.StatusCode = status;
context.Response.Headers["x-request-count"] = status.ToString(); context.Response.Headers["x-request-count"] = status.ToString();
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
@ -533,7 +533,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, method); var responseTask = SendRequestAsync(address, method);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = context.Request.Method + "1"; context.Response.Headers["x-request-count"] = context.Request.Method + "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -546,7 +546,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address, method); responseTask = SendRequestAsync(address, method);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = context.Request.Method + "2"; context.Response.Headers["x-request-count"] = context.Request.Method + "2";
// Http.sys requires a content-type to cache // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -592,7 +592,7 @@ namespace Microsoft.Net.Http.Server
// Cache the first response // Cache the first response
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = context.Request.Method + "1"; context.Response.Headers["x-request-count"] = context.Request.Method + "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -606,7 +606,7 @@ namespace Microsoft.Net.Http.Server
// Try to clear the cache with a second request // Try to clear the cache with a second request
responseTask = SendRequestAsync(address, method); responseTask = SendRequestAsync(address, method);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = context.Request.Method + "2"; context.Response.Headers["x-request-count"] = context.Request.Method + "2";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Dispose(); context.Dispose();
@ -637,7 +637,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "GET", "x-vary", "vary1"); var responseTask = SendRequestAsync(address, "GET", "x-vary", "vary1");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.Headers["vary"] = "x-vary"; context.Response.Headers["vary"] = "x-vary";
@ -668,7 +668,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123"); var responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -681,7 +681,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123"); responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123");
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Dispose(); context.Dispose();
@ -702,7 +702,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -715,7 +715,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123"); responseTask = SendRequestAsync(address, "GET", "Authorization", "Basic abc123");
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Dispose(); context.Dispose();
@ -738,7 +738,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "GET", "Pragma", "no-cache"); var responseTask = SendRequestAsync(address, "GET", "Pragma", "no-cache");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -767,7 +767,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -795,7 +795,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "GET", "Cache-Control", "no-cache"); var responseTask = SendRequestAsync(address, "GET", "Cache-Control", "no-cache");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -823,7 +823,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -851,7 +851,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -879,7 +879,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.CacheTtl = TimeSpan.FromSeconds(10); context.Response.CacheTtl = TimeSpan.FromSeconds(10);
@ -906,7 +906,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "GET", "Range", "bytes=0-10"); var responseTask = SendRequestAsync(address, "GET", "Range", "bytes=0-10");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 206; context.Response.StatusCode = 206;
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
@ -923,7 +923,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address, "GET", "Range", "bytes=0-10"); responseTask = SendRequestAsync(address, "GET", "Range", "bytes=0-10");
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Response.StatusCode = 206; context.Response.StatusCode = 206;
context.Response.Headers["x-request-count"] = "2"; context.Response.Headers["x-request-count"] = "2";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
@ -951,7 +951,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength = 100; context.Response.ContentLength = 100;
@ -981,7 +981,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength = 100; context.Response.ContentLength = 100;
@ -1011,7 +1011,7 @@ namespace Microsoft.Net.Http.Server
var responseLength = _fileLength / 2; // Make sure it handles partial files. var responseLength = _fileLength / 2; // Make sure it handles partial files.
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength = responseLength; context.Response.ContentLength = responseLength;
@ -1043,7 +1043,7 @@ namespace Microsoft.Net.Http.Server
var responseLength = _fileLength / 2; // Make sure it handles partial files. var responseLength = _fileLength / 2; // Make sure it handles partial files.
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["x-request-count"] = "1"; context.Response.Headers["x-request-count"] = "1";
context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache context.Response.Headers["content-type"] = "some/thing"; // Http.sys requires a content-type to cache
context.Response.ContentLength = responseLength; context.Response.ContentLength = responseLength;

View File

@ -22,7 +22,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -44,7 +44,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -67,7 +67,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address); Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -89,7 +89,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address, usehttp11: false); Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address, usehttp11: false);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -112,7 +112,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address); Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ContentLength = 20; context.Response.ContentLength = 20;
context.Dispose(); context.Dispose();
@ -135,7 +135,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 204; // No Content context.Response.StatusCode = 204; // No Content
context.Dispose(); context.Dispose();
@ -158,7 +158,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address); Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 204; // No Content context.Response.StatusCode = 204; // No Content
context.Dispose(); context.Dispose();
@ -182,7 +182,7 @@ namespace Microsoft.Net.Http.Server
WebRequest request = WebRequest.Create(address); WebRequest request = WebRequest.Create(address);
Task<WebResponse> responseTask = request.GetResponseAsync(); Task<WebResponse> responseTask = request.GetResponseAsync();
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["WWW-Authenticate"] = "custom1"; responseHeaders["WWW-Authenticate"] = "custom1";
context.Dispose(); context.Dispose();
@ -207,7 +207,7 @@ namespace Microsoft.Net.Http.Server
WebRequest request = WebRequest.Create(address); WebRequest request = WebRequest.Create(address);
Task<WebResponse> responseTask = request.GetResponseAsync(); Task<WebResponse> responseTask = request.GetResponseAsync();
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["WWW-Authenticate"] = new[] { "custom1, and custom2", "custom3" }; responseHeaders["WWW-Authenticate"] = new[] { "custom1, and custom2", "custom3" };
context.Dispose(); context.Dispose();
@ -236,7 +236,7 @@ namespace Microsoft.Net.Http.Server
WebRequest request = WebRequest.Create(address); WebRequest request = WebRequest.Create(address);
Task<WebResponse> responseTask = request.GetResponseAsync(); Task<WebResponse> responseTask = request.GetResponseAsync();
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["Custom-Header1"] = new[] { "custom1, and custom2", "custom3" }; responseHeaders["Custom-Header1"] = new[] { "custom1, and custom2", "custom3" };
context.Dispose(); context.Dispose();
@ -264,7 +264,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["Connection"] = "Close"; responseHeaders["Connection"] = "Close";
context.Dispose(); context.Dispose();
@ -284,7 +284,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -307,7 +307,7 @@ namespace Microsoft.Net.Http.Server
request.Version = new Version(1, 0); request.Version = new Version(1, 0);
Task<HttpResponseMessage> responseTask = client.SendAsync(request); Task<HttpResponseMessage> responseTask = client.SendAsync(request);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["Transfer-Encoding"] = "chunked"; responseHeaders["Transfer-Encoding"] = "chunked";
var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n"); var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n");
@ -335,7 +335,7 @@ namespace Microsoft.Net.Http.Server
// Http.Sys does not support 1.0 keep-alives. // Http.Sys does not support 1.0 keep-alives.
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false, sendKeepAlive: true); Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false, sendKeepAlive: true);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
HttpResponseMessage response = await responseTask; HttpResponseMessage response = await responseTask;
@ -353,7 +353,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["Custom1"] = new[] { "value1a", "value1b" }; responseHeaders["Custom1"] = new[] { "value1a", "value1b" };
@ -389,7 +389,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;
responseHeaders["Custom1"] = new[] { "value1a", "value1b" }; responseHeaders["Custom1"] = new[] { "value1a", "value1b" };
@ -443,7 +443,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var responseHeaders = context.Response.Headers; var responseHeaders = context.Response.Headers;

View File

@ -32,7 +32,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await Assert.ThrowsAsync<FileNotFoundException>(() => await Assert.ThrowsAsync<FileNotFoundException>(() =>
context.Response.SendFileAsync("Missing.txt", 0, null, CancellationToken.None)); context.Response.SendFileAsync("Missing.txt", 0, null, CancellationToken.None));
context.Dispose(); context.Dispose();
@ -49,7 +49,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -70,7 +70,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(RelativeFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(RelativeFilePath, 0, null, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -91,7 +91,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -112,7 +112,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -134,7 +134,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, FileLength / 2, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, FileLength / 2, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -155,7 +155,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await Assert.ThrowsAsync<ArgumentOutOfRangeException>( await Assert.ThrowsAsync<ArgumentOutOfRangeException>(
() => context.Response.SendFileAsync(AbsoluteFilePath, 1234567, null, CancellationToken.None)); () => context.Response.SendFileAsync(AbsoluteFilePath, 1234567, null, CancellationToken.None));
context.Dispose(); context.Dispose();
@ -172,7 +172,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await Assert.ThrowsAsync<ArgumentOutOfRangeException>( await Assert.ThrowsAsync<ArgumentOutOfRangeException>(
() => context.Response.SendFileAsync(AbsoluteFilePath, 0, 1234567, CancellationToken.None)); () => context.Response.SendFileAsync(AbsoluteFilePath, 0, 1234567, CancellationToken.None));
context.Dispose(); context.Dispose();
@ -189,7 +189,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -214,7 +214,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
await context.Response.SendFileAsync(emptyFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(emptyFilePath, 0, null, CancellationToken.None);
Assert.True(context.Response.HasStartedSending); Assert.True(context.Response.HasStartedSending);
await context.Response.Body.WriteAsync(new byte[10], 0, 10, CancellationToken.None); await context.Response.Body.WriteAsync(new byte[10], 0, 10, CancellationToken.None);
@ -238,7 +238,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = FileLength.ToString(); context.Response.Headers["Content-lenGth"] = FileLength.ToString();
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
@ -260,7 +260,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = "10"; context.Response.Headers["Content-lenGth"] = "10";
await context.Response.SendFileAsync(AbsoluteFilePath, 0, 10, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, 10, CancellationToken.None);
context.Dispose(); context.Dispose();
@ -283,7 +283,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.Headers["Content-lenGth"] = "0"; context.Response.Headers["Content-lenGth"] = "0";
await context.Response.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None); await context.Response.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None);
context.Dispose(); context.Dispose();

View File

@ -18,7 +18,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Equal(200, context.Response.StatusCode); Assert.Equal(200, context.Response.StatusCode);
context.Dispose(); context.Dispose();
@ -38,7 +38,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 201; context.Response.StatusCode = 201;
// TODO: env["owin.ResponseProtocol"] = "HTTP/1.0"; // Http.Sys ignores this value // TODO: env["owin.ResponseProtocol"] = "HTTP/1.0"; // Http.Sys ignores this value
context.Dispose(); context.Dispose();
@ -59,7 +59,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 201; context.Response.StatusCode = 201;
context.Response.ReasonPhrase = "CustomReasonPhrase"; context.Response.ReasonPhrase = "CustomReasonPhrase";
// TODO: env["owin.ResponseProtocol"] = "HTTP/1.0"; // Http.Sys ignores this value // TODO: env["owin.ResponseProtocol"] = "HTTP/1.0"; // Http.Sys ignores this value
@ -81,7 +81,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.StatusCode = 901; context.Response.StatusCode = 901;
context.Dispose(); context.Dispose();
@ -100,7 +100,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Throws<ArgumentOutOfRangeException>(() => { context.Response.StatusCode = 100; }); Assert.Throws<ArgumentOutOfRangeException>(() => { context.Response.StatusCode = 100; });
context.Dispose(); context.Dispose();
@ -116,7 +116,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> responseTask = SendRequestAsync(address); Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Throws<ArgumentOutOfRangeException>(() => { context.Response.StatusCode = 0; }); Assert.Throws<ArgumentOutOfRangeException>(() => { context.Response.StatusCode = 0; });
context.Dispose(); context.Dispose();

View File

@ -23,7 +23,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
var response = await responseTask; var response = await responseTask;
@ -39,7 +39,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<string> responseTask = SendRequestAsync(address); Task<string> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Response.ContentLength = 11; context.Response.ContentLength = 11;
using (var writer = new StreamWriter(context.Response.Body)) using (var writer = new StreamWriter(context.Response.Body))
{ {
@ -59,7 +59,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address, "Hello World"); var responseTask = SendRequestAsync(address, "Hello World");
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
string input = new StreamReader(context.Request.Body).ReadToEnd(); string input = new StreamReader(context.Request.Body).ReadToEnd();
Assert.Equal("Hello World", input); Assert.Equal("Hello World", input);
context.Response.ContentLength = 11; context.Response.ContentLength = 11;
@ -86,7 +86,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = client.GetAsync(address); var responseTask = client.GetAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var ct = context.DisconnectToken; var ct = context.DisconnectToken;
Assert.True(ct.CanBeCanceled, "CanBeCanceled"); Assert.True(ct.CanBeCanceled, "CanBeCanceled");
Assert.False(ct.IsCancellationRequested, "IsCancellationRequested"); Assert.False(ct.IsCancellationRequested, "IsCancellationRequested");
@ -115,7 +115,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var ct = context.DisconnectToken; var ct = context.DisconnectToken;
Assert.True(ct.CanBeCanceled, "CanBeCanceled"); Assert.True(ct.CanBeCanceled, "CanBeCanceled");
Assert.False(ct.IsCancellationRequested, "IsCancellationRequested"); Assert.False(ct.IsCancellationRequested, "IsCancellationRequested");
@ -125,7 +125,7 @@ namespace Microsoft.Net.Http.Server
Assert.True(ct.IsCancellationRequested, "IsCancellationRequested"); Assert.True(ct.IsCancellationRequested, "IsCancellationRequested");
#if !NETCOREAPP1_0 #if !NETCOREAPP1_0
// HttpClient re-tries the request because it doesn't know if the request was received. // HttpClient re-tries the request because it doesn't know if the request was received.
context = await server.GetContextAsync(); context = await server.AcceptAsync();
context.Abort(); context.Abort();
#endif #endif
await Assert.ThrowsAsync<HttpRequestException>(() => responseTask); await Assert.ThrowsAsync<HttpRequestException>(() => responseTask);
@ -143,7 +143,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
var ct = context.DisconnectToken; var ct = context.DisconnectToken;
Assert.True(ct.CanBeCanceled, "CanBeCanceled"); Assert.True(ct.CanBeCanceled, "CanBeCanceled");
Assert.False(ct.IsCancellationRequested, "IsCancellationRequested"); Assert.False(ct.IsCancellationRequested, "IsCancellationRequested");
@ -174,7 +174,7 @@ namespace Microsoft.Net.Http.Server
server.SetRequestQueueLimit(1001); server.SetRequestQueueLimit(1001);
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
context.Dispose(); context.Dispose();
var response = await responseTask; var response = await responseTask;
@ -190,7 +190,7 @@ namespace Microsoft.Net.Http.Server
{ {
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Equal(string.Empty, context.Request.PathBase); Assert.Equal(string.Empty, context.Request.PathBase);
Assert.Equal("/", context.Request.Path); Assert.Equal("/", context.Request.Path);
context.Dispose(); context.Dispose();
@ -203,7 +203,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
Assert.Equal("/pathbase", context.Request.PathBase); Assert.Equal("/pathbase", context.Request.PathBase);
Assert.Equal("/", context.Request.Path); Assert.Equal("/", context.Request.Path);
context.Dispose(); context.Dispose();
@ -223,7 +223,7 @@ namespace Microsoft.Net.Http.Server
server.UrlPrefixes.Add(address); server.UrlPrefixes.Add(address);
var responseTask = SendRequestAsync(address); var responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.Equal("/pathbase", context.Request.PathBase); Assert.Equal("/pathbase", context.Request.PathBase);
Assert.Equal("/", context.Request.Path); Assert.Equal("/", context.Request.Path);
context.Dispose(); context.Dispose();
@ -235,7 +235,7 @@ namespace Microsoft.Net.Http.Server
responseTask = SendRequestAsync(address); responseTask = SendRequestAsync(address);
context = await server.GetContextAsync(); context = await server.AcceptAsync();
Assert.Equal(string.Empty, context.Request.PathBase); Assert.Equal(string.Empty, context.Request.PathBase);
Assert.Equal("/pathbase/", context.Request.Path); Assert.Equal("/pathbase/", context.Request.Path);
context.Dispose(); context.Dispose();

View File

@ -22,7 +22,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<HttpResponseMessage> clientTask = SendRequestAsync(address); Task<HttpResponseMessage> clientTask = SendRequestAsync(address);
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
byte[] body = Encoding.UTF8.GetBytes("Hello World"); byte[] body = Encoding.UTF8.GetBytes("Hello World");
context.Response.Body.Write(body, 0, body.Length); context.Response.Body.Write(body, 0, body.Length);
@ -43,7 +43,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<WebSocket> clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address)); Task<WebSocket> clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address));
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.True(context.IsUpgradableRequest); Assert.True(context.IsUpgradableRequest);
WebSocket serverWebSocket = await context.AcceptWebSocketAsync(); WebSocket serverWebSocket = await context.AcceptWebSocketAsync();
WebSocket clientWebSocket = await clientTask; WebSocket clientWebSocket = await clientTask;
@ -61,7 +61,7 @@ namespace Microsoft.Net.Http.Server
{ {
Task<WebSocket> clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address)); Task<WebSocket> clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address));
var context = await server.GetContextAsync(); var context = await server.AcceptAsync();
Assert.True(context.IsWebSocketRequest()); Assert.True(context.IsWebSocketRequest());
WebSocket serverWebSocket = await context.AcceptWebSocketAsync(); WebSocket serverWebSocket = await context.AcceptWebSocketAsync();
WebSocket clientWebSocket = await clientTask; WebSocket clientWebSocket = await clientTask;