#216 Lazy feature initialization
This commit is contained in:
parent
9f1476aea8
commit
efef52a0ad
|
|
@ -19,7 +19,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
@ -63,17 +62,19 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
private string _rawTarget;
|
private string _rawTarget;
|
||||||
private IPAddress _remoteIpAddress;
|
private IPAddress _remoteIpAddress;
|
||||||
private IPAddress _localIpAddress;
|
private IPAddress _localIpAddress;
|
||||||
private int? _remotePort;
|
private int _remotePort;
|
||||||
private int? _localPort;
|
private int _localPort;
|
||||||
private string _connectionId;
|
private string _connectionId;
|
||||||
private string _requestId;
|
private string _traceIdentitfier;
|
||||||
private X509Certificate2 _clientCert;
|
private X509Certificate2 _clientCert;
|
||||||
private ClaimsPrincipal _user;
|
private ClaimsPrincipal _user;
|
||||||
private IAuthenticationHandler _authHandler;
|
private IAuthenticationHandler _authHandler;
|
||||||
private CancellationToken? _disconnectToken;
|
private CancellationToken _disconnectToken;
|
||||||
private Stream _responseStream;
|
private Stream _responseStream;
|
||||||
private IHeaderDictionary _responseHeaders;
|
private IHeaderDictionary _responseHeaders;
|
||||||
|
|
||||||
|
private Fields _initializedFields;
|
||||||
|
|
||||||
private List<Tuple<Func<object, Task>, object>> _onStartingActions = new List<Tuple<Func<object, Task>, object>>();
|
private List<Tuple<Func<object, Task>, object>> _onStartingActions = new List<Tuple<Func<object, Task>, object>>();
|
||||||
private List<Tuple<Func<object, Task>, object>> _onCompletedActions = new List<Tuple<Func<object, Task>, object>>();
|
private List<Tuple<Func<object, Task>, object>> _onCompletedActions = new List<Tuple<Func<object, Task>, object>>();
|
||||||
private bool _responseStarted;
|
private bool _responseStarted;
|
||||||
|
|
@ -85,91 +86,95 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
_features = new FeatureCollection(new StandardFeatureCollection(this));
|
_features = new FeatureCollection(new StandardFeatureCollection(this));
|
||||||
_authHandler = new AuthenticationHandler(requestContext);
|
_authHandler = new AuthenticationHandler(requestContext);
|
||||||
_enableResponseCaching = enableResponseCaching;
|
_enableResponseCaching = enableResponseCaching;
|
||||||
|
|
||||||
|
// Pre-initialize any fields that are not lazy at the lower level.
|
||||||
|
_requestHeaders = new HeaderDictionary(Request.Headers);
|
||||||
|
_httpMethod = Request.Method;
|
||||||
|
_path = Request.Path;
|
||||||
|
_pathBase = Request.PathBase;
|
||||||
|
_query = Request.QueryString;
|
||||||
|
_rawTarget = Request.RawUrl;
|
||||||
|
_scheme = Request.Scheme;
|
||||||
|
_user = _requestContext.User;
|
||||||
|
|
||||||
_responseStream = new ResponseStream(requestContext.Response.Body, OnStart);
|
_responseStream = new ResponseStream(requestContext.Response.Body, OnStart);
|
||||||
|
_responseHeaders = new HeaderDictionary(Response.Headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IFeatureCollection Features
|
internal IFeatureCollection Features => _features;
|
||||||
|
|
||||||
|
internal object RequestContext => _requestContext;
|
||||||
|
|
||||||
|
private Request Request => _requestContext.Request;
|
||||||
|
|
||||||
|
private Response Response => _requestContext.Response;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
// Fields that may be lazy-initialized
|
||||||
|
private enum Fields
|
||||||
{
|
{
|
||||||
get { return _features; }
|
None = 0x0,
|
||||||
|
Protocol = 0x1,
|
||||||
|
RequestBody = 0x2,
|
||||||
|
RequestAborted = 0x4,
|
||||||
|
LocalIpAddress = 0x8,
|
||||||
|
RemoteIpAddress = 0x10,
|
||||||
|
LocalPort = 0x20,
|
||||||
|
RemotePort = 0x40,
|
||||||
|
ConnectionId = 0x80,
|
||||||
|
ClientCertificate = 0x100,
|
||||||
|
TraceIdentifier = 0x200,
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object RequestContext
|
private bool IsNotInitialized(Fields field)
|
||||||
{
|
{
|
||||||
get { return _requestContext; }
|
return (_initializedFields & field) != field;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Request Request
|
private void SetInitialized(Fields field)
|
||||||
{
|
{
|
||||||
get { return _requestContext.Request; }
|
_initializedFields |= field;
|
||||||
}
|
|
||||||
|
|
||||||
private Response Response
|
|
||||||
{
|
|
||||||
get { return _requestContext.Response; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream IHttpRequestFeature.Body
|
Stream IHttpRequestFeature.Body
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_requestBody == null)
|
if (IsNotInitialized(Fields.RequestBody))
|
||||||
{
|
{
|
||||||
_requestBody = Request.Body;
|
_requestBody = Request.Body;
|
||||||
|
SetInitialized(Fields.RequestBody);
|
||||||
}
|
}
|
||||||
return _requestBody;
|
return _requestBody;
|
||||||
}
|
}
|
||||||
set { _requestBody = value; }
|
set
|
||||||
|
{
|
||||||
|
_requestBody = value;
|
||||||
|
SetInitialized(Fields.RequestBody);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IHeaderDictionary IHttpRequestFeature.Headers
|
IHeaderDictionary IHttpRequestFeature.Headers
|
||||||
{
|
{
|
||||||
get
|
get { return _requestHeaders; }
|
||||||
{
|
|
||||||
if (_requestHeaders == null)
|
|
||||||
{
|
|
||||||
_requestHeaders = new HeaderDictionary(Request.Headers);
|
|
||||||
}
|
|
||||||
return _requestHeaders;
|
|
||||||
}
|
|
||||||
set { _requestHeaders = value; }
|
set { _requestHeaders = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.Method
|
string IHttpRequestFeature.Method
|
||||||
{
|
{
|
||||||
get
|
get { return _httpMethod; }
|
||||||
{
|
|
||||||
if (_httpMethod == null)
|
|
||||||
{
|
|
||||||
_httpMethod = Request.Method;
|
|
||||||
}
|
|
||||||
return _httpMethod;
|
|
||||||
}
|
|
||||||
set { _httpMethod = value; }
|
set { _httpMethod = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.Path
|
string IHttpRequestFeature.Path
|
||||||
{
|
{
|
||||||
get
|
get { return _path; }
|
||||||
{
|
|
||||||
if (_path == null)
|
|
||||||
{
|
|
||||||
_path = Request.Path;
|
|
||||||
}
|
|
||||||
return _path;
|
|
||||||
}
|
|
||||||
set { _path = value; }
|
set { _path = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.PathBase
|
string IHttpRequestFeature.PathBase
|
||||||
{
|
{
|
||||||
get
|
get { return _pathBase; }
|
||||||
{
|
|
||||||
if (_pathBase == null)
|
|
||||||
{
|
|
||||||
_pathBase = Request.PathBase;
|
|
||||||
}
|
|
||||||
return _pathBase;
|
|
||||||
}
|
|
||||||
set { _pathBase = value; }
|
set { _pathBase = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,63 +182,47 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_httpProtocolVersion == null)
|
if (IsNotInitialized(Fields.Protocol))
|
||||||
{
|
{
|
||||||
if (Request.ProtocolVersion.Major == 1)
|
var protocol = Request.ProtocolVersion;
|
||||||
|
if (protocol.Major == 1 && protocol.Minor == 1)
|
||||||
{
|
{
|
||||||
if (Request.ProtocolVersion.Minor == 1)
|
_httpProtocolVersion = "HTTP/1.1";
|
||||||
{
|
|
||||||
_httpProtocolVersion = "HTTP/1.1";
|
|
||||||
}
|
|
||||||
else if (Request.ProtocolVersion.Minor == 0)
|
|
||||||
{
|
|
||||||
_httpProtocolVersion = "HTTP/1.0";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (protocol.Major == 1 && protocol.Minor == 0)
|
||||||
_httpProtocolVersion = "HTTP/" + Request.ProtocolVersion.ToString(2);
|
{
|
||||||
|
_httpProtocolVersion = "HTTP/1.0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_httpProtocolVersion = "HTTP/" + protocol.ToString(2);
|
||||||
|
}
|
||||||
|
SetInitialized(Fields.Protocol);
|
||||||
}
|
}
|
||||||
return _httpProtocolVersion;
|
return _httpProtocolVersion;
|
||||||
}
|
}
|
||||||
set { _httpProtocolVersion = value; }
|
set
|
||||||
|
{
|
||||||
|
_httpProtocolVersion = value;
|
||||||
|
SetInitialized(Fields.Protocol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.QueryString
|
string IHttpRequestFeature.QueryString
|
||||||
{
|
{
|
||||||
get
|
get { return _query; }
|
||||||
{
|
|
||||||
if (_query == null)
|
|
||||||
{
|
|
||||||
_query = Request.QueryString;
|
|
||||||
}
|
|
||||||
return _query;
|
|
||||||
}
|
|
||||||
set { _query = value; }
|
set { _query = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.RawTarget
|
string IHttpRequestFeature.RawTarget
|
||||||
{
|
{
|
||||||
get
|
get { return _rawTarget; }
|
||||||
{
|
|
||||||
if (_rawTarget == null)
|
|
||||||
{
|
|
||||||
_rawTarget = Request.RawUrl;
|
|
||||||
}
|
|
||||||
return _rawTarget;
|
|
||||||
}
|
|
||||||
set { _rawTarget = value; }
|
set { _rawTarget = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpRequestFeature.Scheme
|
string IHttpRequestFeature.Scheme
|
||||||
{
|
{
|
||||||
get
|
get { return _scheme; }
|
||||||
{
|
|
||||||
if (_scheme == null)
|
|
||||||
{
|
|
||||||
_scheme = Request.Scheme;
|
|
||||||
}
|
|
||||||
return _scheme;
|
|
||||||
}
|
|
||||||
set { _scheme = value; }
|
set { _scheme = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,85 +230,116 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_localIpAddress == null)
|
if (IsNotInitialized(Fields.LocalIpAddress))
|
||||||
{
|
{
|
||||||
_localIpAddress = Request.LocalIpAddress;
|
_localIpAddress = Request.LocalIpAddress;
|
||||||
|
SetInitialized(Fields.LocalIpAddress);
|
||||||
}
|
}
|
||||||
return _localIpAddress;
|
return _localIpAddress;
|
||||||
}
|
}
|
||||||
set { _localIpAddress = value; }
|
set
|
||||||
|
{
|
||||||
|
_localIpAddress = value;
|
||||||
|
SetInitialized(Fields.LocalIpAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IPAddress IHttpConnectionFeature.RemoteIpAddress
|
IPAddress IHttpConnectionFeature.RemoteIpAddress
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_remoteIpAddress == null)
|
if (IsNotInitialized(Fields.RemoteIpAddress))
|
||||||
{
|
{
|
||||||
_remoteIpAddress = Request.RemoteIpAddress;
|
_remoteIpAddress = Request.RemoteIpAddress;
|
||||||
|
SetInitialized(Fields.RemoteIpAddress);
|
||||||
}
|
}
|
||||||
return _remoteIpAddress;
|
return _remoteIpAddress;
|
||||||
}
|
}
|
||||||
set { _remoteIpAddress = value; }
|
set
|
||||||
|
{
|
||||||
|
_remoteIpAddress = value;
|
||||||
|
SetInitialized(Fields.RemoteIpAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IHttpConnectionFeature.LocalPort
|
int IHttpConnectionFeature.LocalPort
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_localPort == null)
|
if (IsNotInitialized(Fields.LocalPort))
|
||||||
{
|
{
|
||||||
_localPort = Request.LocalPort;
|
_localPort = Request.LocalPort;
|
||||||
|
SetInitialized(Fields.LocalPort);
|
||||||
}
|
}
|
||||||
return _localPort.Value;
|
return _localPort;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_localPort = value;
|
||||||
|
SetInitialized(Fields.LocalPort);
|
||||||
}
|
}
|
||||||
set { _localPort = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int IHttpConnectionFeature.RemotePort
|
int IHttpConnectionFeature.RemotePort
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_remotePort == null)
|
if (IsNotInitialized(Fields.RemotePort))
|
||||||
{
|
{
|
||||||
_remotePort = Request.RemotePort;
|
_remotePort = Request.RemotePort;
|
||||||
|
SetInitialized(Fields.RemotePort);
|
||||||
}
|
}
|
||||||
return _remotePort.Value;
|
return _remotePort;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_remotePort = value;
|
||||||
|
SetInitialized(Fields.RemotePort);
|
||||||
}
|
}
|
||||||
set { _remotePort = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string IHttpConnectionFeature.ConnectionId
|
string IHttpConnectionFeature.ConnectionId
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_connectionId == null)
|
if (IsNotInitialized(Fields.ConnectionId))
|
||||||
{
|
{
|
||||||
_connectionId = Request.ConnectionId.ToString(CultureInfo.InvariantCulture);
|
_connectionId = Request.ConnectionId.ToString(CultureInfo.InvariantCulture);
|
||||||
|
SetInitialized(Fields.ConnectionId);
|
||||||
}
|
}
|
||||||
return _connectionId;
|
return _connectionId;
|
||||||
}
|
}
|
||||||
set { _connectionId = value; }
|
set
|
||||||
|
{
|
||||||
|
_connectionId = value;
|
||||||
|
SetInitialized(Fields.ConnectionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X509Certificate2 ITlsConnectionFeature.ClientCertificate
|
X509Certificate2 ITlsConnectionFeature.ClientCertificate
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_clientCert == null)
|
if (IsNotInitialized(Fields.ClientCertificate))
|
||||||
{
|
{
|
||||||
_clientCert = Request.GetClientCertificateAsync().Result; // TODO: Sync;
|
_clientCert = Request.GetClientCertificateAsync().Result; // TODO: Sync;
|
||||||
|
SetInitialized(Fields.ClientCertificate);
|
||||||
}
|
}
|
||||||
return _clientCert;
|
return _clientCert;
|
||||||
}
|
}
|
||||||
set { _clientCert = value; }
|
set
|
||||||
|
{
|
||||||
|
_clientCert = value;
|
||||||
|
SetInitialized(Fields.ClientCertificate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task<X509Certificate2> ITlsConnectionFeature.GetClientCertificateAsync(CancellationToken cancellationToken)
|
async Task<X509Certificate2> ITlsConnectionFeature.GetClientCertificateAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_clientCert == null)
|
if (IsNotInitialized(Fields.ClientCertificate))
|
||||||
{
|
{
|
||||||
_clientCert = await Request.GetClientCertificateAsync(cancellationToken);
|
_clientCert = await Request.GetClientCertificateAsync(cancellationToken);
|
||||||
|
SetInitialized(Fields.ClientCertificate);
|
||||||
}
|
}
|
||||||
return _clientCert;
|
return _clientCert;
|
||||||
}
|
}
|
||||||
|
|
@ -329,15 +349,9 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
return Request.IsHttps ? this : null;
|
return Request.IsHttps ? this : null;
|
||||||
}
|
}
|
||||||
/* TODO: https://github.com/aspnet/WebListener/issues/231
|
/* TODO: https://github.com/aspnet/WebListener/issues/231
|
||||||
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId()
|
byte[] ITlsTokenBindingFeature.GetProvidedTokenBindingId() => Request.GetProvidedTokenBindingId();
|
||||||
{
|
|
||||||
return Request.GetProvidedTokenBindingId();
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] ITlsTokenBindingFeature.GetReferredTokenBindingId()
|
byte[] ITlsTokenBindingFeature.GetReferredTokenBindingId() => Request.GetReferredTokenBindingId();
|
||||||
{
|
|
||||||
return Request.GetReferredTokenBindingId();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ITlsTokenBindingFeature GetTlsTokenBindingFeature()
|
internal ITlsTokenBindingFeature GetTlsTokenBindingFeature()
|
||||||
{
|
{
|
||||||
|
|
@ -356,34 +370,17 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
|
|
||||||
Stream IHttpResponseFeature.Body
|
Stream IHttpResponseFeature.Body
|
||||||
{
|
{
|
||||||
get
|
get { return _responseStream; }
|
||||||
{
|
|
||||||
if (_responseStream == null)
|
|
||||||
{
|
|
||||||
_responseStream = Response.Body;
|
|
||||||
}
|
|
||||||
return _responseStream;
|
|
||||||
}
|
|
||||||
set { _responseStream = value; }
|
set { _responseStream = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
IHeaderDictionary IHttpResponseFeature.Headers
|
IHeaderDictionary IHttpResponseFeature.Headers
|
||||||
{
|
{
|
||||||
get
|
get { return _responseHeaders; }
|
||||||
{
|
|
||||||
if (_responseHeaders == null)
|
|
||||||
{
|
|
||||||
_responseHeaders = new HeaderDictionary(Response.Headers);
|
|
||||||
}
|
|
||||||
return _responseHeaders;
|
|
||||||
}
|
|
||||||
set { _responseHeaders = value; }
|
set { _responseHeaders = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IHttpResponseFeature.HasStarted
|
bool IHttpResponseFeature.HasStarted => Response.HasStarted;
|
||||||
{
|
|
||||||
get { return Response.HasStarted; }
|
|
||||||
}
|
|
||||||
|
|
||||||
void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
|
void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
|
||||||
{
|
{
|
||||||
|
|
@ -435,24 +432,23 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!_disconnectToken.HasValue)
|
if (IsNotInitialized(Fields.RequestAborted))
|
||||||
{
|
{
|
||||||
_disconnectToken = _requestContext.DisconnectToken;
|
_disconnectToken = _requestContext.DisconnectToken;
|
||||||
|
SetInitialized(Fields.RequestAborted);
|
||||||
}
|
}
|
||||||
return _disconnectToken.Value;
|
return _disconnectToken;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_disconnectToken = value;
|
||||||
|
SetInitialized(Fields.RequestAborted);
|
||||||
}
|
}
|
||||||
set { _disconnectToken = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHttpRequestLifetimeFeature.Abort()
|
void IHttpRequestLifetimeFeature.Abort() => _requestContext.Abort();
|
||||||
{
|
|
||||||
_requestContext.Abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IHttpUpgradeFeature.IsUpgradableRequest
|
bool IHttpUpgradeFeature.IsUpgradableRequest => _requestContext.IsUpgradableRequest;
|
||||||
{
|
|
||||||
get { return _requestContext.IsUpgradableRequest; }
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task<Stream> IHttpUpgradeFeature.UpgradeAsync()
|
async Task<Stream> IHttpUpgradeFeature.UpgradeAsync()
|
||||||
{
|
{
|
||||||
|
|
@ -477,14 +473,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
|
|
||||||
ClaimsPrincipal IHttpAuthenticationFeature.User
|
ClaimsPrincipal IHttpAuthenticationFeature.User
|
||||||
{
|
{
|
||||||
get
|
get { return _user; }
|
||||||
{
|
|
||||||
if (_user == null)
|
|
||||||
{
|
|
||||||
_user = _requestContext.User;
|
|
||||||
}
|
|
||||||
return _user;
|
|
||||||
}
|
|
||||||
set { _user = value; }
|
set { _user = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,13 +487,18 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_requestId == null)
|
if (IsNotInitialized(Fields.TraceIdentifier))
|
||||||
{
|
{
|
||||||
_requestId = _requestContext.TraceIdentifier.ToString();
|
_traceIdentitfier = _requestContext.TraceIdentifier.ToString();
|
||||||
|
SetInitialized(Fields.TraceIdentifier);
|
||||||
}
|
}
|
||||||
return _requestId;
|
return _traceIdentitfier;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_traceIdentitfier = value;
|
||||||
|
SetInitialized(Fields.TraceIdentifier);
|
||||||
}
|
}
|
||||||
set { _requestId = value; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task OnStart()
|
internal async Task OnStart()
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -34,7 +35,7 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
public class RequestTests
|
public class RequestTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Request_SimpleGet_Success()
|
public async Task Request_SimpleGet_ExpectedFieldsSet()
|
||||||
{
|
{
|
||||||
string root;
|
string root;
|
||||||
using (Utilities.CreateHttpServerReturnRoot("/basepath", out root, httpContext =>
|
using (Utilities.CreateHttpServerReturnRoot("/basepath", out root, httpContext =>
|
||||||
|
|
@ -54,14 +55,12 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
Assert.Equal("/basepath/SomePath?SomeQuery", requestInfo.RawTarget);
|
Assert.Equal("/basepath/SomePath?SomeQuery", requestInfo.RawTarget);
|
||||||
Assert.Equal("HTTP/1.1", requestInfo.Protocol);
|
Assert.Equal("HTTP/1.1", requestInfo.Protocol);
|
||||||
|
|
||||||
// Server Keys
|
|
||||||
// TODO: Assert.NotNull(httpContext.Get<IDictionary<string, object>>("server.Capabilities"));
|
|
||||||
|
|
||||||
var connectionInfo = httpContext.Features.Get<IHttpConnectionFeature>();
|
var connectionInfo = httpContext.Features.Get<IHttpConnectionFeature>();
|
||||||
Assert.Equal("::1", connectionInfo.RemoteIpAddress.ToString());
|
Assert.Equal("::1", connectionInfo.RemoteIpAddress.ToString());
|
||||||
Assert.NotEqual(0, connectionInfo.RemotePort);
|
Assert.NotEqual(0, connectionInfo.RemotePort);
|
||||||
Assert.Equal("::1", connectionInfo.LocalIpAddress.ToString());
|
Assert.Equal("::1", connectionInfo.LocalIpAddress.ToString());
|
||||||
Assert.NotEqual(0, connectionInfo.LocalPort);
|
Assert.NotEqual(0, connectionInfo.LocalPort);
|
||||||
|
Assert.NotNull(connectionInfo.ConnectionId);
|
||||||
|
|
||||||
// Trace identifier
|
// Trace identifier
|
||||||
var requestIdentifierFeature = httpContext.Features.Get<IHttpRequestIdentifierFeature>();
|
var requestIdentifierFeature = httpContext.Features.Get<IHttpRequestIdentifierFeature>();
|
||||||
|
|
@ -83,6 +82,133 @@ namespace Microsoft.AspNetCore.Server.WebListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Request_FieldsCanBeSet_Set()
|
||||||
|
{
|
||||||
|
string root;
|
||||||
|
using (Utilities.CreateHttpServerReturnRoot("/basepath", out root, httpContext =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var requestInfo = httpContext.Features.Get<IHttpRequestFeature>();
|
||||||
|
|
||||||
|
// Request Keys
|
||||||
|
requestInfo.Method = "TEST";
|
||||||
|
Assert.Equal("TEST", requestInfo.Method);
|
||||||
|
requestInfo.Body = new MemoryStream();
|
||||||
|
Assert.IsType<MemoryStream>(requestInfo.Body);
|
||||||
|
var customHeaders = new HeaderDictionary(new HeaderCollection());
|
||||||
|
requestInfo.Headers = customHeaders;
|
||||||
|
Assert.Same(customHeaders, requestInfo.Headers);
|
||||||
|
requestInfo.Scheme = "abcd";
|
||||||
|
Assert.Equal("abcd", requestInfo.Scheme);
|
||||||
|
requestInfo.PathBase = "/customized/Base";
|
||||||
|
Assert.Equal("/customized/Base", requestInfo.PathBase);
|
||||||
|
requestInfo.Path = "/customized/Path";
|
||||||
|
Assert.Equal("/customized/Path", requestInfo.Path);
|
||||||
|
requestInfo.QueryString = "?customizedQuery";
|
||||||
|
Assert.Equal("?customizedQuery", requestInfo.QueryString);
|
||||||
|
requestInfo.RawTarget = "/customized/raw?Target";
|
||||||
|
Assert.Equal("/customized/raw?Target", requestInfo.RawTarget);
|
||||||
|
requestInfo.Protocol = "Custom/2.0";
|
||||||
|
Assert.Equal("Custom/2.0", requestInfo.Protocol);
|
||||||
|
|
||||||
|
var connectionInfo = httpContext.Features.Get<IHttpConnectionFeature>();
|
||||||
|
connectionInfo.RemoteIpAddress = IPAddress.Broadcast;
|
||||||
|
Assert.Equal(IPAddress.Broadcast, connectionInfo.RemoteIpAddress);
|
||||||
|
connectionInfo.RemotePort = 12345;
|
||||||
|
Assert.Equal(12345, connectionInfo.RemotePort);
|
||||||
|
connectionInfo.LocalIpAddress = IPAddress.Any;
|
||||||
|
Assert.Equal(IPAddress.Any, connectionInfo.LocalIpAddress);
|
||||||
|
connectionInfo.LocalPort = 54321;
|
||||||
|
Assert.Equal(54321, connectionInfo.LocalPort);
|
||||||
|
connectionInfo.ConnectionId = "CustomId";
|
||||||
|
Assert.Equal("CustomId", connectionInfo.ConnectionId);
|
||||||
|
|
||||||
|
// Trace identifier
|
||||||
|
var requestIdentifierFeature = httpContext.Features.Get<IHttpRequestIdentifierFeature>();
|
||||||
|
Assert.NotNull(requestIdentifierFeature);
|
||||||
|
requestIdentifierFeature.TraceIdentifier = "customTrace";
|
||||||
|
Assert.Equal("customTrace", requestIdentifierFeature.TraceIdentifier);
|
||||||
|
|
||||||
|
// Note: Response keys are validated in the ResponseTests
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
byte[] body = Encoding.ASCII.GetBytes(ex.ToString());
|
||||||
|
httpContext.Response.Body.Write(body, 0, body.Length);
|
||||||
|
}
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
string response = await SendRequestAsync(root + "/basepath/SomePath?SomeQuery");
|
||||||
|
Assert.Equal(string.Empty, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Request_FieldsCanBeSetToNull_Set()
|
||||||
|
{
|
||||||
|
string root;
|
||||||
|
using (Utilities.CreateHttpServerReturnRoot("/basepath", out root, httpContext =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var requestInfo = httpContext.Features.Get<IHttpRequestFeature>();
|
||||||
|
|
||||||
|
// Request Keys
|
||||||
|
requestInfo.Method = null;
|
||||||
|
Assert.Null(requestInfo.Method);
|
||||||
|
requestInfo.Body = null;
|
||||||
|
Assert.Null(requestInfo.Body);
|
||||||
|
requestInfo.Headers = null;
|
||||||
|
Assert.Null(requestInfo.Headers);
|
||||||
|
requestInfo.Scheme = null;
|
||||||
|
Assert.Null(requestInfo.Scheme);
|
||||||
|
requestInfo.PathBase = null;
|
||||||
|
Assert.Null(requestInfo.PathBase);
|
||||||
|
requestInfo.Path = null;
|
||||||
|
Assert.Null(requestInfo.Path);
|
||||||
|
requestInfo.QueryString = null;
|
||||||
|
Assert.Null(requestInfo.QueryString);
|
||||||
|
requestInfo.RawTarget = null;
|
||||||
|
Assert.Null(requestInfo.RawTarget);
|
||||||
|
requestInfo.Protocol = null;
|
||||||
|
Assert.Null(requestInfo.Protocol);
|
||||||
|
|
||||||
|
var connectionInfo = httpContext.Features.Get<IHttpConnectionFeature>();
|
||||||
|
connectionInfo.RemoteIpAddress = null;
|
||||||
|
Assert.Null(connectionInfo.RemoteIpAddress);
|
||||||
|
connectionInfo.RemotePort = -1;
|
||||||
|
Assert.Equal(-1, connectionInfo.RemotePort);
|
||||||
|
connectionInfo.LocalIpAddress = null;
|
||||||
|
Assert.Null(connectionInfo.LocalIpAddress);
|
||||||
|
connectionInfo.LocalPort = -1;
|
||||||
|
Assert.Equal(-1, connectionInfo.LocalPort);
|
||||||
|
connectionInfo.ConnectionId = null;
|
||||||
|
Assert.Null(connectionInfo.ConnectionId);
|
||||||
|
|
||||||
|
// Trace identifier
|
||||||
|
var requestIdentifierFeature = httpContext.Features.Get<IHttpRequestIdentifierFeature>();
|
||||||
|
Assert.NotNull(requestIdentifierFeature);
|
||||||
|
requestIdentifierFeature.TraceIdentifier = null;
|
||||||
|
Assert.Null(requestIdentifierFeature.TraceIdentifier);
|
||||||
|
|
||||||
|
// Note: Response keys are validated in the ResponseTests
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
byte[] body = Encoding.ASCII.GetBytes(ex.ToString());
|
||||||
|
httpContext.Response.Body.Write(body, 0, body.Length);
|
||||||
|
}
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
string response = await SendRequestAsync(root + "/basepath/SomePath?SomeQuery");
|
||||||
|
Assert.Equal(string.Empty, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("/", "/", "", "/")]
|
[InlineData("/", "/", "", "/")]
|
||||||
[InlineData("/basepath/", "/basepath", "/basepath", "")]
|
[InlineData("/basepath/", "/basepath", "/basepath", "")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue