Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit b466c3b

Browse files
committed
Reacting to Hosting changes
1 parent af2c32f commit b466c3b

19 files changed

+212
-142
lines changed

src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,10 @@ public async Task RequestProcessingAsync()
206206
ResponseBody = new FrameResponseStream(this);
207207
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
208208

209+
var httpContext = HttpContextFactory.Create(this);
209210
try
210211
{
211-
await Application.Invoke(this).ConfigureAwait(false);
212+
await Application.Invoke(httpContext).ConfigureAwait(false);
212213
}
213214
catch (Exception ex)
214215
{
@@ -227,6 +228,8 @@ public async Task RequestProcessingAsync()
227228

228229
await FireOnCompleted();
229230

231+
HttpContextFactory.Dispose(httpContext);
232+
230233
await ProduceEnd();
231234

232235
while (await RequestBody.ReadAsync(_nullBuffer, 0, _nullBuffer.Length) != 0)

src/Microsoft.AspNet.Server.Kestrel/Http/Listener.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Threading.Tasks;
6+
using Microsoft.AspNet.Http;
67
using Microsoft.AspNet.Server.Kestrel.Networking;
78
using Microsoft.Extensions.Logging;
89

@@ -23,7 +24,7 @@ protected Listener(ServiceContext serviceContext)
2324
public Task StartAsync(
2425
ServerAddress address,
2526
KestrelThread thread,
26-
Func<Frame, Task> application)
27+
RequestDelegate application)
2728
{
2829
ServerAddress = address;
2930
Thread = thread;

src/Microsoft.AspNet.Server.Kestrel/Http/ListenerContext.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
5-
using System.Threading.Tasks;
4+
using Microsoft.AspNet.Http;
65
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
76

87
namespace Microsoft.AspNet.Server.Kestrel.Http
@@ -34,7 +33,7 @@ public ListenerContext(ListenerContext listenerContext)
3433

3534
public KestrelThread Thread { get; set; }
3635

37-
public Func<Frame, Task> Application { get; set; }
36+
public RequestDelegate Application { get; set; }
3837

3938
public MemoryPool2 Memory2 { get; set; }
4039
}

src/Microsoft.AspNet.Server.Kestrel/Http/ListenerPrimary.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNet.Http;
78
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
89
using Microsoft.AspNet.Server.Kestrel.Networking;
910
using Microsoft.Extensions.Logging;
@@ -33,7 +34,7 @@ public async Task StartAsync(
3334
string pipeName,
3435
ServerAddress address,
3536
KestrelThread thread,
36-
Func<Frame, Task> application)
37+
RequestDelegate application)
3738
{
3839
await StartAsync(address, thread, application).ConfigureAwait(false);
3940

src/Microsoft.AspNet.Server.Kestrel/Http/ListenerSecondary.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Runtime.InteropServices;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNet.Http;
78
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
89
using Microsoft.AspNet.Server.Kestrel.Networking;
910
using Microsoft.Extensions.Logging;
@@ -26,7 +27,7 @@ public Task StartAsync(
2627
string pipeName,
2728
ServerAddress address,
2829
KestrelThread thread,
29-
Func<Frame, Task> application)
30+
RequestDelegate application)
3031
{
3132
ServerAddress = address;
3233
Thread = thread;

src/Microsoft.AspNet.Server.Kestrel/KestrelEngine.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6-
using System.Threading.Tasks;
7-
using Microsoft.AspNet.Http.Features;
6+
using Microsoft.AspNet.Http;
87
using Microsoft.AspNet.Server.Kestrel.Http;
98
using Microsoft.AspNet.Server.Kestrel.Networking;
109

@@ -49,7 +48,7 @@ public void Dispose()
4948
Threads.Clear();
5049
}
5150

52-
public IDisposable CreateServer(ServerAddress address, Func<IFeatureCollection, Task> application)
51+
public IDisposable CreateServer(ServerAddress address, RequestDelegate application)
5352
{
5453
var listeners = new List<IDisposable>();
5554

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using Microsoft.AspNet.Hosting;
7+
using Microsoft.AspNet.Hosting.Server;
8+
using Microsoft.AspNet.Http;
9+
using Microsoft.AspNet.Http.Features;
10+
using Microsoft.AspNet.Server.Kestrel.Http;
11+
using Microsoft.Extensions.Logging;
12+
13+
namespace Microsoft.AspNet.Server.Kestrel
14+
{
15+
public class KestrelServer : IServer
16+
{
17+
private Stack<IDisposable> _disposables;
18+
private readonly IApplicationLifetime _applicationLifetime;
19+
private readonly ILogger _logger;
20+
private readonly IHttpContextFactory _httpContextFactory;
21+
22+
public KestrelServer(IFeatureCollection features, IApplicationLifetime applicationLifetime, ILogger logger, IHttpContextFactory httpContextFactory)
23+
{
24+
if (features == null)
25+
{
26+
throw new ArgumentNullException(nameof(features));
27+
}
28+
29+
if (applicationLifetime == null)
30+
{
31+
throw new ArgumentNullException(nameof(applicationLifetime));
32+
}
33+
34+
if (logger == null)
35+
{
36+
throw new ArgumentNullException(nameof(logger));
37+
}
38+
39+
if (httpContextFactory == null)
40+
{
41+
throw new ArgumentNullException(nameof(httpContextFactory));
42+
}
43+
44+
_applicationLifetime = applicationLifetime;
45+
_logger = logger;
46+
Features = features;
47+
_httpContextFactory = httpContextFactory;
48+
}
49+
50+
public IFeatureCollection Features { get; }
51+
52+
public void Start(RequestDelegate requestDelegate)
53+
{
54+
if (_disposables != null)
55+
{
56+
// The server has already started and/or has not been cleaned up yet
57+
throw new InvalidOperationException("Server has already started.");
58+
}
59+
_disposables = new Stack<IDisposable>();
60+
61+
try
62+
{
63+
var information = (KestrelServerInformation)Features.Get<IKestrelServerInformation>();
64+
var dateHeaderValueManager = new DateHeaderValueManager();
65+
var engine = new KestrelEngine(new ServiceContext
66+
{
67+
AppLifetime = _applicationLifetime,
68+
Log = new KestrelTrace(_logger),
69+
HttpContextFactory = _httpContextFactory,
70+
DateHeaderValueManager = dateHeaderValueManager,
71+
ConnectionFilter = information.ConnectionFilter,
72+
NoDelay = information.NoDelay
73+
});
74+
75+
_disposables.Push(engine);
76+
_disposables.Push(dateHeaderValueManager);
77+
78+
if (information.ThreadCount < 0)
79+
{
80+
throw new ArgumentOutOfRangeException(nameof(information.ThreadCount),
81+
information.ThreadCount,
82+
"ThreadCount cannot be negative");
83+
}
84+
85+
engine.Start(information.ThreadCount == 0 ? 1 : information.ThreadCount);
86+
var atLeastOneListener = false;
87+
88+
foreach (var address in information.Addresses)
89+
{
90+
var parsedAddress = ServerAddress.FromUrl(address);
91+
if (parsedAddress == null)
92+
{
93+
throw new FormatException("Unrecognized listening address: " + address);
94+
}
95+
else
96+
{
97+
atLeastOneListener = true;
98+
_disposables.Push(engine.CreateServer(
99+
parsedAddress,
100+
requestDelegate));
101+
}
102+
}
103+
104+
if (!atLeastOneListener)
105+
{
106+
throw new InvalidOperationException("No recognized listening addresses were configured.");
107+
}
108+
}
109+
catch
110+
{
111+
Dispose();
112+
throw;
113+
}
114+
}
115+
116+
public void Dispose()
117+
{
118+
if (_disposables != null)
119+
{
120+
while (_disposables.Count > 0)
121+
{
122+
_disposables.Pop().Dispose();
123+
}
124+
_disposables = null;
125+
}
126+
}
127+
}
128+
}
Lines changed: 8 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
5-
using System.Collections.Generic;
6-
using System.Threading.Tasks;
74
using Microsoft.AspNet.Hosting;
85
using Microsoft.AspNet.Hosting.Server;
6+
using Microsoft.AspNet.Http;
97
using Microsoft.AspNet.Http.Features;
108
using Microsoft.AspNet.Server.Features;
11-
using Microsoft.AspNet.Server.Kestrel.Http;
129
using Microsoft.Extensions.Configuration;
1310
using Microsoft.Extensions.Logging;
1411

@@ -20,89 +17,24 @@ namespace Microsoft.AspNet.Server.Kestrel
2017
public class ServerFactory : IServerFactory
2118
{
2219
private readonly IApplicationLifetime _appLifetime;
23-
private readonly ILogger _logger;
20+
private readonly ILoggerFactory _loggerFactory;
21+
private readonly IHttpContextFactory _httpContextFactory;
2422

25-
public ServerFactory(IApplicationLifetime appLifetime, ILoggerFactory loggerFactory)
23+
public ServerFactory(IApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IHttpContextFactory httpContextFactory)
2624
{
2725
_appLifetime = appLifetime;
28-
_logger = loggerFactory.CreateLogger("Microsoft.AspNet.Server.Kestrel");
26+
_loggerFactory = loggerFactory;
27+
_httpContextFactory = httpContextFactory;
2928
}
3029

31-
public IFeatureCollection Initialize(IConfiguration configuration)
30+
public IServer CreateServer(IConfiguration configuration)
3231
{
3332
var information = new KestrelServerInformation();
3433
information.Initialize(configuration);
3534
var serverFeatures = new FeatureCollection();
3635
serverFeatures.Set<IKestrelServerInformation>(information);
3736
serverFeatures.Set<IServerAddressesFeature>(information);
38-
return serverFeatures;
39-
}
40-
41-
public IDisposable Start(IFeatureCollection serverFeatures, Func<IFeatureCollection, Task> application)
42-
{
43-
var disposables = new Stack<IDisposable>();
44-
var disposer = new Disposable(() =>
45-
{
46-
foreach (var disposable in disposables)
47-
{
48-
disposable.Dispose();
49-
}
50-
});
51-
52-
try
53-
{
54-
var information = (KestrelServerInformation)serverFeatures.Get<IKestrelServerInformation>();
55-
var dateHeaderValueManager = new DateHeaderValueManager();
56-
var engine = new KestrelEngine(new ServiceContext
57-
{
58-
AppLifetime = _appLifetime,
59-
Log = new KestrelTrace(_logger),
60-
DateHeaderValueManager = dateHeaderValueManager,
61-
ConnectionFilter = information.ConnectionFilter,
62-
NoDelay = information.NoDelay
63-
});
64-
65-
disposables.Push(engine);
66-
disposables.Push(dateHeaderValueManager);
67-
68-
if (information.ThreadCount < 0)
69-
{
70-
throw new ArgumentOutOfRangeException(nameof(information.ThreadCount),
71-
information.ThreadCount,
72-
"ThreadCount cannot be negative");
73-
}
74-
75-
engine.Start(information.ThreadCount == 0 ? 1 : information.ThreadCount);
76-
bool atLeastOneListener = false;
77-
78-
foreach (var address in information.Addresses)
79-
{
80-
var parsedAddress = ServerAddress.FromUrl(address);
81-
if (parsedAddress == null)
82-
{
83-
throw new FormatException("Unrecognized listening address: " + address);
84-
}
85-
else
86-
{
87-
atLeastOneListener = true;
88-
disposables.Push(engine.CreateServer(
89-
parsedAddress,
90-
application));
91-
}
92-
}
93-
94-
if (!atLeastOneListener)
95-
{
96-
throw new InvalidOperationException("No recognized listening addresses were configured.");
97-
}
98-
99-
return disposer;
100-
}
101-
catch
102-
{
103-
disposer.Dispose();
104-
throw;
105-
}
37+
return new KestrelServer(serverFeatures, _appLifetime, _loggerFactory.CreateLogger("Microsoft.AspNet.Server.Kestrel"), _httpContextFactory);
10638
}
10739
}
10840
}

src/Microsoft.AspNet.Server.Kestrel/ServiceContext.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using Microsoft.AspNet.Hosting;
5+
using Microsoft.AspNet.Http;
56
using Microsoft.AspNet.Server.Kestrel.Filter;
67
using Microsoft.AspNet.Server.Kestrel.Http;
78
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
@@ -20,6 +21,7 @@ public ServiceContext(ServiceContext context)
2021
AppLifetime = context.AppLifetime;
2122
Memory = context.Memory;
2223
Log = context.Log;
24+
HttpContextFactory = context.HttpContextFactory;
2325
DateHeaderValueManager = context.DateHeaderValueManager;
2426
ConnectionFilter = context.ConnectionFilter;
2527
NoDelay = context.NoDelay;
@@ -31,6 +33,8 @@ public ServiceContext(ServiceContext context)
3133

3234
public IKestrelTrace Log { get; set; }
3335

36+
public IHttpContextFactory HttpContextFactory { get; set; }
37+
3438
public DateHeaderValueManager DateHeaderValueManager { get; set; }
3539

3640
public IConnectionFilter ConnectionFilter { get; set; }

test/Microsoft.AspNet.Server.Kestrel.FunctionalTests/AddressRegistrationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public async Task RegisterAddresses_Success(string addressInput, string[] testUr
2626
.Build();
2727

2828
var hostBuilder = new WebHostBuilder(config);
29-
hostBuilder.UseServer("Microsoft.AspNet.Server.Kestrel");
29+
hostBuilder.UseServerFactory("Microsoft.AspNet.Server.Kestrel");
3030
hostBuilder.UseStartup(ConfigureEchoAddress);
3131

3232
using (var app = hostBuilder.Build().Start())

test/Microsoft.AspNet.Server.Kestrel.FunctionalTests/RequestTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async Task LargeUpload()
2828
.Build();
2929

3030
var hostBuilder = new WebHostBuilder(config);
31-
hostBuilder.UseServer("Microsoft.AspNet.Server.Kestrel");
31+
hostBuilder.UseServerFactory("Microsoft.AspNet.Server.Kestrel");
3232
hostBuilder.UseStartup(app =>
3333
{
3434
app.Run(async context =>

0 commit comments

Comments
 (0)