Rough implementation of feature collection optimization
This commit is contained in:
parent
0c1b05ce2d
commit
dcf591c832
|
|
@ -19,6 +19,9 @@ namespace SampleApp
|
|||
{
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IApplicationEnvironment env)
|
||||
{
|
||||
var ksi = app.ServerFeatures[typeof(IKestrelServerInformation)] as IKestrelServerInformation;
|
||||
//ksi.ThreadCount = 4;
|
||||
|
||||
loggerFactory.MinimumLevel = LogLevel.Debug;
|
||||
|
||||
loggerFactory.AddConsole(LogLevel.Debug);
|
||||
|
|
@ -46,6 +49,8 @@ namespace SampleApp
|
|||
context.Request.Path,
|
||||
context.Request.QueryString);
|
||||
|
||||
foreach (var q in context.Request.Query) { }
|
||||
|
||||
context.Response.ContentLength = 11;
|
||||
context.Response.ContentType = "text/plain";
|
||||
await context.Response.WriteAsync("Hello world");
|
||||
|
|
|
|||
|
|
@ -2,45 +2,44 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
{
|
||||
public class ServerRequest : IHttpRequestFeature, IHttpResponseFeature, IHttpUpgradeFeature
|
||||
public partial class Frame : IFeatureCollection, IHttpRequestFeature, IHttpResponseFeature, IHttpUpgradeFeature
|
||||
{
|
||||
private Frame _frame;
|
||||
private string _scheme;
|
||||
private string _pathBase;
|
||||
private FeatureCollection _features;
|
||||
private int _featureRevision;
|
||||
|
||||
public ServerRequest(Frame frame)
|
||||
{
|
||||
_frame = frame;
|
||||
_features = new FeatureCollection();
|
||||
PopulateFeatures();
|
||||
}
|
||||
private Dictionary<Type, object> Extra => MaybeExtra ?? Interlocked.CompareExchange(ref MaybeExtra, new Dictionary<Type, object>(), null);
|
||||
private Dictionary<Type, object> MaybeExtra;
|
||||
|
||||
internal IFeatureCollection Features
|
||||
public void ResetFeatureCollection()
|
||||
{
|
||||
get { return _features; }
|
||||
FastReset();
|
||||
MaybeExtra?.Clear();
|
||||
Interlocked.Increment(ref _featureRevision);
|
||||
}
|
||||
|
||||
string IHttpRequestFeature.Protocol
|
||||
{
|
||||
get
|
||||
{
|
||||
return _frame.HttpVersion;
|
||||
return HttpVersion;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.HttpVersion = value;
|
||||
HttpVersion = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,12 +60,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.Method;
|
||||
return Method;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.Method = value;
|
||||
Method = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,12 +86,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.Path;
|
||||
return Path;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.Path = value;
|
||||
Path = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,12 +99,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.QueryString;
|
||||
return QueryString;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.QueryString = value;
|
||||
QueryString = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,12 +112,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.RequestHeaders;
|
||||
return RequestHeaders;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.RequestHeaders = value;
|
||||
RequestHeaders = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,12 +125,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.RequestBody;
|
||||
return RequestBody;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.RequestBody = value;
|
||||
RequestBody = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,12 +138,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.StatusCode;
|
||||
return StatusCode;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.StatusCode = value;
|
||||
StatusCode = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,12 +151,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.ReasonPhrase;
|
||||
return ReasonPhrase;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.ReasonPhrase = value;
|
||||
ReasonPhrase = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,12 +164,12 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.ResponseHeaders;
|
||||
return ResponseHeaders;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.ResponseHeaders = value;
|
||||
ResponseHeaders = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,18 +177,18 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
{
|
||||
get
|
||||
{
|
||||
return _frame.ResponseBody;
|
||||
return ResponseBody;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_frame.ResponseBody = value;
|
||||
ResponseBody = value;
|
||||
}
|
||||
}
|
||||
|
||||
bool IHttpResponseFeature.HasStarted
|
||||
{
|
||||
get { return _frame.HasResponseStarted; }
|
||||
get { return HasResponseStarted; }
|
||||
}
|
||||
|
||||
bool IHttpUpgradeFeature.IsUpgradableRequest
|
||||
|
|
@ -197,7 +196,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
get
|
||||
{
|
||||
StringValues values;
|
||||
if (_frame.RequestHeaders.TryGetValue("Connection", out values))
|
||||
if (RequestHeaders.TryGetValue("Connection", out values))
|
||||
{
|
||||
return values.Any(value => value.IndexOf("upgrade", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
}
|
||||
|
|
@ -205,38 +204,45 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
}
|
||||
}
|
||||
|
||||
private void PopulateFeatures()
|
||||
bool IFeatureCollection.IsReadOnly => false;
|
||||
|
||||
int IFeatureCollection.Revision => _featureRevision;
|
||||
|
||||
object IFeatureCollection.this[Type key]
|
||||
{
|
||||
_features[typeof(IHttpRequestFeature)] = this;
|
||||
_features[typeof(IHttpResponseFeature)] = this;
|
||||
_features[typeof(IHttpUpgradeFeature)] = this;
|
||||
get { return FastFeatureGet(key); }
|
||||
set { FastFeatureSet(key, value); }
|
||||
}
|
||||
|
||||
void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
|
||||
{
|
||||
_frame.OnStarting(callback, state);
|
||||
OnStarting(callback, state);
|
||||
}
|
||||
|
||||
void IHttpResponseFeature.OnCompleted(Func<object, Task> callback, object state)
|
||||
{
|
||||
_frame.OnCompleted(callback, state);
|
||||
OnCompleted(callback, state);
|
||||
}
|
||||
|
||||
Task<Stream> IHttpUpgradeFeature.UpgradeAsync()
|
||||
{
|
||||
_frame.StatusCode = 101;
|
||||
_frame.ReasonPhrase = "Switching Protocols";
|
||||
_frame.ResponseHeaders["Connection"] = "Upgrade";
|
||||
if (!_frame.ResponseHeaders.ContainsKey("Upgrade"))
|
||||
StatusCode = 101;
|
||||
ReasonPhrase = "Switching Protocols";
|
||||
ResponseHeaders["Connection"] = "Upgrade";
|
||||
if (!ResponseHeaders.ContainsKey("Upgrade"))
|
||||
{
|
||||
StringValues values;
|
||||
if (_frame.RequestHeaders.TryGetValue("Upgrade", out values))
|
||||
if (RequestHeaders.TryGetValue("Upgrade", out values))
|
||||
{
|
||||
_frame.ResponseHeaders["Upgrade"] = values;
|
||||
ResponseHeaders["Upgrade"] = values;
|
||||
}
|
||||
}
|
||||
_frame.ProduceStart();
|
||||
return Task.FromResult(_frame.DuplexStream);
|
||||
ProduceStart();
|
||||
return Task.FromResult(DuplexStream);
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<Type, object>> IEnumerable<KeyValuePair<Type, object>>.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => FastEnumerable().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
{
|
||||
public partial class Frame
|
||||
{
|
||||
|
||||
private object _currentIHttpRequestFeature;
|
||||
private object _currentIHttpResponseFeature;
|
||||
private object _currentIHttpUpgradeFeature;
|
||||
private object _currentIHttpRequestIdentifierFeature;
|
||||
private object _currentIHttpConnectionFeature;
|
||||
private object _currentITlsConnectionFeature;
|
||||
private object _currentIServiceProvidersFeature;
|
||||
private object _currentIHttpSendFileFeature;
|
||||
private object _currentIHttpWebSocketFeature;
|
||||
private object _currentIQueryFeature;
|
||||
private object _currentIFormFeature;
|
||||
private object _currentIItemsFeature;
|
||||
private object _currentIHttpAuthenticationFeature;
|
||||
private object _currentIHttpRequestLifetimeFeature;
|
||||
private object _currentISessionFeature;
|
||||
private object _currentIResponseCookiesFeature;
|
||||
|
||||
private void FastReset()
|
||||
{
|
||||
_currentIHttpRequestFeature = this as global::Microsoft.AspNet.Http.Features.IHttpRequestFeature;
|
||||
_currentIHttpResponseFeature = this as global::Microsoft.AspNet.Http.Features.IHttpResponseFeature;
|
||||
_currentIHttpUpgradeFeature = this as global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature;
|
||||
_currentIHttpRequestIdentifierFeature = this as global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature;
|
||||
_currentIHttpConnectionFeature = this as global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature;
|
||||
_currentITlsConnectionFeature = this as global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature;
|
||||
_currentIServiceProvidersFeature = this as global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature;
|
||||
_currentIHttpSendFileFeature = this as global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature;
|
||||
_currentIHttpWebSocketFeature = this as global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature;
|
||||
_currentIQueryFeature = this as global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature;
|
||||
_currentIFormFeature = this as global::Microsoft.AspNet.Http.Features.Internal.IFormFeature;
|
||||
_currentIItemsFeature = this as global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature;
|
||||
_currentIHttpAuthenticationFeature = this as global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature;
|
||||
_currentIHttpRequestLifetimeFeature = this as global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature;
|
||||
_currentISessionFeature = this as global::Microsoft.AspNet.Http.Features.ISessionFeature;
|
||||
_currentIResponseCookiesFeature = this as global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature;
|
||||
}
|
||||
|
||||
private object FastFeatureGet(Type key)
|
||||
{
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature))
|
||||
{
|
||||
return _currentIHttpRequestFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature))
|
||||
{
|
||||
return _currentIHttpResponseFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature))
|
||||
{
|
||||
return _currentIHttpUpgradeFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature))
|
||||
{
|
||||
return _currentIHttpRequestIdentifierFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature))
|
||||
{
|
||||
return _currentIHttpConnectionFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature))
|
||||
{
|
||||
return _currentITlsConnectionFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature))
|
||||
{
|
||||
return _currentIServiceProvidersFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature))
|
||||
{
|
||||
return _currentIHttpSendFileFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature))
|
||||
{
|
||||
return _currentIHttpWebSocketFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature))
|
||||
{
|
||||
return _currentIQueryFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature))
|
||||
{
|
||||
return _currentIFormFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature))
|
||||
{
|
||||
return _currentIItemsFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature))
|
||||
{
|
||||
return _currentIHttpAuthenticationFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature))
|
||||
{
|
||||
return _currentIHttpRequestLifetimeFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.ISessionFeature))
|
||||
{
|
||||
return _currentISessionFeature;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature))
|
||||
{
|
||||
return _currentIResponseCookiesFeature;
|
||||
}
|
||||
object feature = null;
|
||||
if (MaybeExtra?.TryGetValue(key, out feature) ?? false)
|
||||
{
|
||||
return feature;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void FastFeatureSet(Type key, object feature)
|
||||
{
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature))
|
||||
{
|
||||
_currentIHttpRequestFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature))
|
||||
{
|
||||
_currentIHttpResponseFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature))
|
||||
{
|
||||
_currentIHttpUpgradeFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature))
|
||||
{
|
||||
_currentIHttpRequestIdentifierFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature))
|
||||
{
|
||||
_currentIHttpConnectionFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature))
|
||||
{
|
||||
_currentITlsConnectionFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature))
|
||||
{
|
||||
_currentIServiceProvidersFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature))
|
||||
{
|
||||
_currentIHttpSendFileFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature))
|
||||
{
|
||||
_currentIHttpWebSocketFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature))
|
||||
{
|
||||
_currentIQueryFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature))
|
||||
{
|
||||
_currentIFormFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature))
|
||||
{
|
||||
_currentIItemsFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature))
|
||||
{
|
||||
_currentIHttpAuthenticationFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature))
|
||||
{
|
||||
_currentIHttpRequestLifetimeFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.ISessionFeature))
|
||||
{
|
||||
_currentISessionFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
if (key == typeof(global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature))
|
||||
{
|
||||
_currentIResponseCookiesFeature = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}
|
||||
Extra[key] = feature;
|
||||
}
|
||||
|
||||
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
|
||||
{
|
||||
if (_currentIHttpRequestFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestFeature), _currentIHttpRequestFeature);
|
||||
}
|
||||
if (_currentIHttpResponseFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpResponseFeature), _currentIHttpResponseFeature);
|
||||
}
|
||||
if (_currentIHttpUpgradeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpUpgradeFeature), _currentIHttpUpgradeFeature);
|
||||
}
|
||||
if (_currentIHttpRequestIdentifierFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestIdentifierFeature), _currentIHttpRequestIdentifierFeature);
|
||||
}
|
||||
if (_currentIHttpConnectionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpConnectionFeature), _currentIHttpConnectionFeature);
|
||||
}
|
||||
if (_currentITlsConnectionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.ITlsConnectionFeature), _currentITlsConnectionFeature);
|
||||
}
|
||||
if (_currentIServiceProvidersFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Internal.IServiceProvidersFeature), _currentIServiceProvidersFeature);
|
||||
}
|
||||
if (_currentIHttpSendFileFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpSendFileFeature), _currentIHttpSendFileFeature);
|
||||
}
|
||||
if (_currentIHttpWebSocketFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpWebSocketFeature), _currentIHttpWebSocketFeature);
|
||||
}
|
||||
if (_currentIQueryFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Internal.IQueryFeature), _currentIQueryFeature);
|
||||
}
|
||||
if (_currentIFormFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Internal.IFormFeature), _currentIFormFeature);
|
||||
}
|
||||
if (_currentIItemsFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Internal.IItemsFeature), _currentIItemsFeature);
|
||||
}
|
||||
if (_currentIHttpAuthenticationFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Authentication.IHttpAuthenticationFeature), _currentIHttpAuthenticationFeature);
|
||||
}
|
||||
if (_currentIHttpRequestLifetimeFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.IHttpRequestLifetimeFeature), _currentIHttpRequestLifetimeFeature);
|
||||
}
|
||||
if (_currentISessionFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.ISessionFeature), _currentISessionFeature);
|
||||
}
|
||||
if (_currentIResponseCookiesFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::Microsoft.AspNet.Http.Features.Internal.IResponseCookiesFeature), _currentIResponseCookiesFeature);
|
||||
}
|
||||
if (MaybeExtra != null)
|
||||
{
|
||||
foreach(var item in MaybeExtra)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,14 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
|
@ -16,7 +18,7 @@ using Microsoft.Extensions.Primitives;
|
|||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
{
|
||||
public class Frame : FrameContext, IFrameControl
|
||||
public partial class Frame : FrameContext, IFrameControl
|
||||
{
|
||||
private static readonly Encoding _ascii = Encoding.ASCII;
|
||||
private static readonly ArraySegment<byte> _endChunkBytes = CreateAsciiByteArraySegment("\r\n");
|
||||
|
|
@ -80,6 +82,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
_requestHeaders.Reset();
|
||||
ResetResponseHeaders();
|
||||
ResetFeatureCollection();
|
||||
|
||||
Method = null;
|
||||
RequestUri = null;
|
||||
|
|
@ -725,5 +728,5 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
statusCode != 205 &&
|
||||
statusCode != 304;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Server.Kestrel.Http;
|
||||
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
|
||||
using Microsoft.AspNet.Server.Kestrel.Networking;
|
||||
|
|
@ -98,7 +99,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
Threads.Clear();
|
||||
}
|
||||
|
||||
public IDisposable CreateServer(ServerAddress address, Func<Frame, Task> application)
|
||||
public IDisposable CreateServer(ServerAddress address, Func<IFeatureCollection, Task> application)
|
||||
{
|
||||
var listeners = new List<IDisposable>();
|
||||
|
||||
|
|
|
|||
|
|
@ -88,11 +88,7 @@ namespace Microsoft.AspNet.Server.Kestrel
|
|||
atLeastOneListener = true;
|
||||
disposables.Push(engine.CreateServer(
|
||||
parsedAddress,
|
||||
async frame =>
|
||||
{
|
||||
var request = new ServerRequest(frame);
|
||||
await application.Invoke(request.Features).ConfigureAwait(false);
|
||||
}));
|
||||
application));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
"scripts": {
|
||||
"prepare": [
|
||||
"dnu restore ../../tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode",
|
||||
"dnx -p ../../tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode run Http/FrameHeaders.Generated.cs"
|
||||
"dnx -p ../../tools/Microsoft.AspNet.Server.Kestrel.GeneratedCode run Http/FrameHeaders.Generated.cs Http/Frame.Generated.cs"
|
||||
],
|
||||
"postrestore": [
|
||||
"dnu restore ../../tools/Microsoft.AspNet.Server.Kestrel.LibuvCopier",
|
||||
|
|
@ -65,6 +65,5 @@
|
|||
"runtimes/win7-x86/native/": "runtimes/win7-x86/native/*",
|
||||
"runtimes/win10-arm/native/": "runtimes/win10-arm/native/*",
|
||||
"runtimes/osx/native/": "runtimes/osx/native/*"
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.Dnx.Compilation.CSharp;
|
||||
using Microsoft.AspNet.Http.Features.Internal;
|
||||
using Microsoft.AspNet.Http.Features.Authentication;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.GeneratedCode
|
||||
{
|
||||
// This project can output the Class library as a NuGet Package.
|
||||
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
|
||||
public class FrameFeatureCollection : ICompileModule
|
||||
{
|
||||
static string Each<T>(IEnumerable<T> values, Func<T, string> formatter)
|
||||
{
|
||||
return values.Select(formatter).Aggregate((a, b) => a + b);
|
||||
}
|
||||
|
||||
public virtual void BeforeCompile(BeforeCompileContext context)
|
||||
{
|
||||
var syntaxTree = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(GeneratedFile());
|
||||
context.Compilation = context.Compilation.AddSyntaxTrees(syntaxTree);
|
||||
}
|
||||
|
||||
public static string GeneratedFile()
|
||||
{
|
||||
var commonFeatures = new[]
|
||||
{
|
||||
typeof(IHttpRequestFeature),
|
||||
typeof(IHttpResponseFeature),
|
||||
typeof(IHttpRequestIdentifierFeature),
|
||||
typeof(IHttpSendFileFeature),
|
||||
typeof(IServiceProvidersFeature),
|
||||
typeof(IHttpAuthenticationFeature),
|
||||
typeof(IHttpRequestLifetimeFeature),
|
||||
typeof(IQueryFeature),
|
||||
typeof(IFormFeature),
|
||||
typeof(IResponseCookiesFeature),
|
||||
typeof(IItemsFeature),
|
||||
typeof(IHttpConnectionFeature),
|
||||
typeof(ITlsConnectionFeature),
|
||||
typeof(IHttpUpgradeFeature),
|
||||
typeof(IHttpWebSocketFeature),
|
||||
typeof(ISessionFeature),
|
||||
};
|
||||
|
||||
return $@"
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||
{{
|
||||
public partial class Frame
|
||||
{{
|
||||
{Each(commonFeatures, feature => $@"
|
||||
private object _current{feature.Name};")}
|
||||
|
||||
private void FastReset()
|
||||
{{{Each(commonFeatures, feature => $@"
|
||||
_current{feature.Name} = this as global::{feature.FullName};")}
|
||||
}}
|
||||
|
||||
private object FastFeatureGet(Type key)
|
||||
{{{Each(commonFeatures, feature => $@"
|
||||
if (key == typeof(global::{feature.FullName}))
|
||||
{{
|
||||
return _current{feature.Name};
|
||||
}}")}
|
||||
object feature = null;
|
||||
if (MaybeExtra?.TryGetValue(key, out feature) ?? false)
|
||||
{{
|
||||
return feature;
|
||||
}}
|
||||
return null;
|
||||
}}
|
||||
|
||||
private void FastFeatureSet(Type key, object feature)
|
||||
{{{Each(commonFeatures, feature => $@"
|
||||
if (key == typeof(global::{feature.FullName}))
|
||||
{{
|
||||
_current{feature.Name} = feature;
|
||||
System.Threading.Interlocked.Increment(ref _featureRevision);
|
||||
return;
|
||||
}}")}
|
||||
Extra[key] = feature;
|
||||
}}
|
||||
|
||||
private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
|
||||
{{{Each(commonFeatures, feature => $@"
|
||||
if (_current{feature.Name} != null)
|
||||
{{
|
||||
yield return new KeyValuePair<Type, object>(typeof(global::{feature.FullName}), _current{feature.Name});
|
||||
}}")}
|
||||
if (MaybeExtra != null)
|
||||
{{
|
||||
foreach(var item in MaybeExtra)
|
||||
{{
|
||||
yield return item;
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
";
|
||||
}
|
||||
|
||||
public virtual void AfterCompile(AfterCompileContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,19 +7,34 @@ namespace Microsoft.AspNet.Server.Kestrel.GeneratedCode
|
|||
{
|
||||
public int Main(string[] args)
|
||||
{
|
||||
var text = KnownHeaders.GeneratedFile();
|
||||
var text0 = KnownHeaders.GeneratedFile();
|
||||
var text1 = FrameFeatureCollection.GeneratedFile();
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
var existing = File.Exists(args[0]) ? File.ReadAllText(args[0]) : "";
|
||||
if (!string.Equals(text, existing))
|
||||
if (!string.Equals(text0, existing))
|
||||
{
|
||||
File.WriteAllText(args[0], text);
|
||||
File.WriteAllText(args[0], text0);
|
||||
}
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
{
|
||||
var existing0 = File.Exists(args[0]) ? File.ReadAllText(args[0]) : "";
|
||||
if (!string.Equals(text0, existing0))
|
||||
{
|
||||
File.WriteAllText(args[0], text0);
|
||||
}
|
||||
|
||||
var existing1 = File.Exists(args[1]) ? File.ReadAllText(args[1]) : "";
|
||||
if (!string.Equals(text1, existing1))
|
||||
{
|
||||
File.WriteAllText(args[1], text1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(text);
|
||||
Console.WriteLine(text0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
{
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*"
|
||||
"Microsoft.Dnx.Compilation.CSharp.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Features": "1.0.0-*",
|
||||
"Microsoft.AspNet.Hosting": "1.0.0-*"
|
||||
},
|
||||
|
||||
"commands": {
|
||||
|
|
|
|||
Loading…
Reference in New Issue