Reputation: 2241
Is it possible to open a web socket and connect to the end user, but only through a particular route?
Let's assume that I have a web API which has the following functionalities:
article section on route: /articles
chat module on route: /chat
At this moment I have a web socket middleware which handles all the ws request independently on root which is used by the end user.
So, theoretically web socket connection could be established in any place of the front layer of an application if I just write the code which will be able to do it.
I don't want it, so how can I prevent those situations?
Below is my current solution:
using System;
using System.IO;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace chat.Framework
{
public class WebSocketMiddleware
{
private readonly RequestDelegate _next;
private WebSocketHandler _webSocketHandler;
public WebSocketMiddleware(RequestDelegate next, WebSocketHandler webSocketHandler)
{
_next = next;
_webSocketHandler = webSocketHandler;
}
public async Task Invoke(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
{
await _next.Invoke(context);
return;
}
var socket = await context.WebSockets.AcceptWebSocketAsync();
await _webSocketHandler.OnConnected(socket);
await Recive(socket, async(result, buffer) =>
{
if(result.MessageType == WebSocketMessageType.Text)
{
await _webSocketHandler.Recive(socket, result, buffer);
return;
}
else if (result.MessageType == WebSocketMessageType.Close)
{
await _webSocketHandler.OnDisconnected(socket);
Console.WriteLine("Disconnect");
return;
}
});
}
private async Task Recive(WebSocket socket, Action<WebSocketReceiveResult, byte[]> handle)
{
var buffer = new ArraySegment<byte>(new Byte[1024 * 4]);
WebSocketReceiveResult result = null;
var ms = new MemoryStream();
while(socket.State == WebSocketState.Open)
{
do
{
result = await socket.ReceiveAsync(buffer, CancellationToken.None);
} while (!result.EndOfMessage);
var newBuffer = new byte[result.Count];
Array.Copy(buffer.Array, newBuffer, result.Count);
handle(result, newBuffer);
Console.WriteLine(newBuffer.Length);
}
}
}
}
Upvotes: 0
Views: 1459
Reputation: 6294
ASP.NET Core Middleware run on every single request, so if you want to do routing logic, you need to implement it inside your middleware. For your two routes, this should be pretty simple, just check context.Request.Path
in your Invoke
method before accepting the WebSocket in order to determine which kind of connection to handle.
Upvotes: 1