Adding "server.urls" configuration support to kestrel

This commit is contained in:
Louis DeJardin 2014-06-17 22:45:53 -07:00
parent 6ac6419f4f
commit 17e566c5d1
13 changed files with 167 additions and 34 deletions

View File

@ -25,6 +25,7 @@
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="ServerAddress.cs" />
<Compile Include="ServerFactory.cs" />
<Compile Include="ServerInformation.cs" />
<Compile Include="ServerRequest.cs" />

View File

@ -0,0 +1,10 @@
namespace Kestrel
{
public class ServerAddress
{
public string Host { get; internal set; }
public string Path { get; internal set; }
public int Port { get; internal set; }
public string Scheme { get; internal set; }
}
}

View File

@ -4,6 +4,7 @@ using Microsoft.AspNet.Builder;
using Microsoft.Framework.ConfigurationModel;
using System.Threading.Tasks;
using Microsoft.AspNet.Server.Kestrel;
using System.Collections.Generic;
namespace Kestrel
{
@ -21,15 +22,30 @@ namespace Kestrel
public IDisposable Start(IServerInformation serverInformation, Func<object, Task> application)
{
var disposables = new List<IDisposable>();
var information = (ServerInformation)serverInformation;
var engine = new KestrelEngine();
engine.Start(1);
engine.CreateServer(async frame =>
foreach (var address in information.Addresses)
{
var request = new ServerRequest(frame);
await application.Invoke(request);
disposables.Add(engine.CreateServer(
address.Scheme,
address.Host,
address.Port,
async frame =>
{
var request = new ServerRequest(frame);
await application.Invoke(request);
}));
}
disposables.Add(engine);
return new Disposable(() =>
{
foreach (var disposable in disposables)
{
disposable.Dispose();
}
});
return engine;
}
}
}

View File

@ -1,13 +1,43 @@
using System;
using Microsoft.AspNet.Builder;
using Microsoft.Framework.ConfigurationModel;
using System.Globalization;
using System.Collections.Generic;
namespace Kestrel
{
public class ServerInformation : IServerInformation
{
public ServerInformation()
{
Addresses = new List<ServerAddress>();
}
public void Initialize(IConfiguration configuration)
{
string urls;
if (!configuration.TryGet("server.urls", out urls))
{
urls = "http://+:5000/";
}
foreach (var url in urls.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
string scheme;
string host;
int port;
string path;
if (DeconstructUrl(url, out scheme, out host, out port, out path))
{
Addresses.Add(
new ServerAddress
{
Scheme = scheme,
Host = host,
Port = port,
Path = path
});
}
}
}
public string Name
@ -17,5 +47,68 @@ namespace Kestrel
return "Kestrel";
}
}
public IList<ServerAddress> Addresses { get; private set; }
internal static bool DeconstructUrl(
string url,
out string scheme,
out string host,
out int port,
out string path)
{
url = url ?? string.Empty;
int delimiterStart1 = url.IndexOf("://", StringComparison.Ordinal);
if (delimiterStart1 < 0)
{
scheme = null;
host = null;
port = 0;
path = null;
return false;
}
int delimiterEnd1 = delimiterStart1 + "://".Length;
int delimiterStart3 = url.IndexOf("/", delimiterEnd1, StringComparison.Ordinal);
if (delimiterStart3 < 0)
{
delimiterStart3 = url.Length;
}
int delimiterStart2 = url.LastIndexOf(":", delimiterStart3 - 1, delimiterStart3 - delimiterEnd1, StringComparison.Ordinal);
int delimiterEnd2 = delimiterStart2 + ":".Length;
if (delimiterStart2 < 0)
{
delimiterStart2 = delimiterStart3;
delimiterEnd2 = delimiterStart3;
}
scheme = url.Substring(0, delimiterStart1);
string portString = url.Substring(delimiterEnd2, delimiterStart3 - delimiterEnd2);
int portNumber;
if (int.TryParse(portString, NumberStyles.Integer, CultureInfo.InvariantCulture, out portNumber))
{
host = url.Substring(delimiterEnd1, delimiterStart2 - delimiterEnd1);
port = portNumber;
}
else
{
if (string.Equals(scheme, "http", StringComparison.OrdinalIgnoreCase))
{
port = 80;
}
else if (string.Equals(scheme, "https", StringComparison.OrdinalIgnoreCase))
{
port = 443;
}
else
{
port = 0;
}
host = url.Substring(delimiterEnd1, delimiterStart3 - delimiterEnd1);
}
path = url.Substring(delimiterStart3);
return true;
}
}
}
}

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
WriteAsync(buffer, offset, count).Wait();
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)

View File

@ -45,33 +45,35 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
Memory = memory;
}
public Task StartAsync(KestrelThread thread, Func<Frame, Task> application)
public Task StartAsync(
string scheme,
string host,
int port,
KestrelThread thread,
Func<Frame, Task> application)
{
Thread = thread;
Application = application;
var tcs = new TaskCompletionSource<int>();
Thread.Post(OnStart, tcs);
Thread.Post(_ =>
{
try
{
ListenSocket = new UvTcpHandle();
ListenSocket.Init(Thread.Loop);
ListenSocket.Bind(new IPEndPoint(IPAddress.Any, port));
ListenSocket.Listen(10, _connectionCallback, this);
tcs.SetResult(0);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}, null);
return tcs.Task;
}
public void OnStart(object parameter)
{
var tcs = (TaskCompletionSource<int>)parameter;
try
{
ListenSocket = new UvTcpHandle();
ListenSocket.Init(Thread.Loop);
ListenSocket.Bind(new IPEndPoint(IPAddress.Any, 4001));
ListenSocket.Listen(10, _connectionCallback, this);
tcs.SetResult(0);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
private void OnConnection(UvStreamHandle listenSocket, int status)
{
var acceptSocket = new UvTcpHandle();

View File

@ -48,13 +48,13 @@ namespace Microsoft.AspNet.Server.Kestrel
Threads.Clear();
}
public IDisposable CreateServer(Func<Frame, Task> application)
public IDisposable CreateServer(string scheme, string host, int port, Func<Frame, Task> application)
{
var listeners = new List<Listener>();
foreach (var thread in Threads)
{
var listener = new Listener(Memory);
listener.StartAsync(thread, application).Wait();
listener.StartAsync(scheme, host, port, thread, application).Wait();
listeners.Add(listener);
}
return new Disposable(() =>

View File

@ -0,0 +1,4 @@

Server=Kestrel
; Server = Microsoft.AspNet.Server.WebListener
Server.Urls = http://localhost:5000/

View File

@ -33,6 +33,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="libuv.dll" />
<Content Include="Microsoft.AspNet.Hosting.ini" />
<Content Include="project.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />

View File

@ -1,6 +1,7 @@
{
"dependencies": {
"Kestrel": "0.1-alpha-*"
"Kestrel": "0.1-alpha-*",
"Microsoft.AspNet.Server.WebListener": "0.1-alpha-*"
},
"configurations": {
"net45": { },
@ -11,6 +12,7 @@
}
},
"commands": {
"web": "Microsoft.AspNet.Hosting --server kestrel"
"run": "Microsoft.AspNet.Hosting",
"web": "Microsoft.AspNet.Hosting"
}
}

View File

@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Server.KestralTests
{
var engine = new KestrelEngine();
engine.Start(1);
var started = engine.CreateServer(App);
var started = engine.CreateServer("http", "localhost", 54321, App);
started.Dispose();
engine.Dispose();
}
@ -70,10 +70,10 @@ namespace Microsoft.AspNet.Server.KestralTests
{
var engine = new KestrelEngine();
engine.Start(1);
var started = engine.CreateServer(App);
var started = engine.CreateServer("http", "localhost", 54321, App);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Loopback, 4001));
socket.Connect(new IPEndPoint(IPAddress.Loopback, 54321));
socket.Send(Encoding.ASCII.GetBytes("POST / HTTP/1.0\r\n\r\nHello World"));
socket.Shutdown(SocketShutdown.Send);
var buffer = new byte[8192];

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Server.KestralTests
public void Create()
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Connect(new IPEndPoint(IPAddress.Loopback, 4001));
_socket.Connect(new IPEndPoint(IPAddress.Loopback, 54321));
_stream = new NetworkStream(_socket, false);
_reader = new StreamReader(_stream, Encoding.ASCII);

View File

@ -22,7 +22,11 @@ namespace Microsoft.AspNet.Server.KestralTests
{
_engine = new KestrelEngine();
_engine.Start(1);
_server = _engine.CreateServer(app);
_server = _engine.CreateServer(
"http",
"localhost",
54321,
app);
}