Adding Upgrade support, using WebSocket middleware from sample app
This commit is contained in:
parent
5e51783087
commit
7c626431a1
|
|
@ -3,10 +3,12 @@ using Microsoft.AspNet.Server.Kestrel.Http;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Kestrel
|
||||
{
|
||||
public class ServerRequest : IHttpRequestFeature, IHttpResponseFeature
|
||||
public class ServerRequest : IHttpRequestFeature, IHttpResponseFeature, IHttpOpaqueUpgradeFeature
|
||||
{
|
||||
Frame _frame;
|
||||
string _scheme;
|
||||
|
|
@ -172,9 +174,40 @@ namespace Kestrel
|
|||
_frame.ResponseBody = value;
|
||||
}
|
||||
}
|
||||
|
||||
void IHttpResponseFeature.OnSendingHeaders(Action<object> callback, object state)
|
||||
{
|
||||
_frame.OnSendingHeaders(callback, state);
|
||||
}
|
||||
|
||||
bool IHttpOpaqueUpgradeFeature.IsUpgradableRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] values;
|
||||
if (_frame.RequestHeaders.TryGetValue("Connection", out values))
|
||||
{
|
||||
return values.Any(value => value.IndexOf("upgrade", StringComparison.OrdinalIgnoreCase) != -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<Stream> IHttpOpaqueUpgradeFeature.UpgradeAsync()
|
||||
{
|
||||
_frame.StatusCode = 101;
|
||||
_frame.ReasonPhrase = "Switching Protocols";
|
||||
_frame.ResponseHeaders["Connection"] = new string[] { "Upgrade" };
|
||||
if (!_frame.ResponseHeaders.ContainsKey("Upgrade"))
|
||||
{
|
||||
string[] values;
|
||||
if (_frame.RequestHeaders.TryGetValue("Upgrade", out values))
|
||||
{
|
||||
_frame.ResponseHeaders["Upgrade"] = values;
|
||||
}
|
||||
}
|
||||
_frame.ProduceStart();
|
||||
return _frame.DuplexStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
|
||||
List<KeyValuePair<Action<object>, object>> _onSendingHeaders;
|
||||
object _onSendingHeadersSync = new Object();
|
||||
Stream _duplexStream;
|
||||
|
||||
public Frame(ConnectionContext context) : base(context)
|
||||
{
|
||||
|
|
@ -87,6 +86,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
public IDictionary<string, string[]> ResponseHeaders { get; set; }
|
||||
public Stream ResponseBody { get; set; }
|
||||
|
||||
public Stream DuplexStream { get; set; }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
public bool LocalIntakeFin
|
||||
|
|
@ -175,7 +177,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
_keepAlive = MessageBody.RequestKeepAlive;
|
||||
RequestBody = new FrameRequestStream(MessageBody);
|
||||
ResponseBody = new FrameResponseStream(this);
|
||||
_duplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
|
||||
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
|
||||
SocketInput.Free();
|
||||
Task.Run(ExecuteAsync);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using Microsoft.AspNet.Builder;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
|
|
@ -7,6 +10,8 @@ namespace SampleApp
|
|||
{
|
||||
public void Configure(IBuilder app)
|
||||
{
|
||||
app.UseWebSockets();
|
||||
|
||||
app.Run(async context =>
|
||||
{
|
||||
Console.WriteLine("{0} {1}{2}{3}",
|
||||
|
|
@ -15,10 +20,44 @@ namespace SampleApp
|
|||
context.Request.Path,
|
||||
context.Request.QueryString);
|
||||
|
||||
context.Response.ContentLength = 11;
|
||||
context.Response.ContentType = "text/plain";
|
||||
await context.Response.WriteAsync("Hello world");
|
||||
if (context.IsWebSocketRequest)
|
||||
{
|
||||
var webSocket = await context.AcceptWebSocketAsync();
|
||||
await EchoAsync(webSocket);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.ContentLength = 11;
|
||||
context.Response.ContentType = "text/plain";
|
||||
await context.Response.WriteAsync("Hello world");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task EchoAsync(WebSocket webSocket)
|
||||
{
|
||||
var buffer = new ArraySegment<byte>(new byte[8192]);
|
||||
for (; ;)
|
||||
{
|
||||
var result = await webSocket.ReceiveAsync(
|
||||
buffer,
|
||||
CancellationToken.None);
|
||||
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (result.MessageType == WebSocketMessageType.Text)
|
||||
{
|
||||
Console.WriteLine("{0}", System.Text.Encoding.UTF8.GetString(buffer.Array, 0, result.Count));
|
||||
}
|
||||
|
||||
await webSocket.SendAsync(
|
||||
new ArraySegment<byte>(buffer.Array, 0, result.Count),
|
||||
result.MessageType,
|
||||
result.EndOfMessage,
|
||||
CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
"version": "1.0.0-*",
|
||||
"dependencies": {
|
||||
"Kestrel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*"
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.WebSockets.Middleware": "1.0.0-*"
|
||||
},
|
||||
"configurations": {
|
||||
"net45": { },
|
||||
|
|
|
|||
Loading…
Reference in New Issue