From 1b1eb17bee360a4d42fa191663a0c0ce508ec213 Mon Sep 17 00:00:00 2001 From: Dmitri Shimanski Date: Sat, 29 Mar 2025 02:54:54 +0300 Subject: [PATCH] adds comments, OOP incapsulation and publish package to nuget --- Examples/ChatController.cs | 4 ++-- Examples/TestWebSocketServer.cs | 8 +++---- README.md | 8 +++---- .../Core/WebSocketManagerTest.cs | 5 ++-- yawaflua.WebSockets/Core/WebSocket.cs | 4 ++-- .../Models/Abstracts/WebSocketController.cs | 11 ++++++++- .../Models/Interfaces/IWebSocket.cs | 24 +++++++++++++++++++ .../Models/Interfaces/IWebSocketClient.cs | 22 +++++++++++++++++ .../Models/Interfaces/IWebSocketController.cs | 8 ++++++- .../Models/Interfaces/IWebSocketManager.cs | 21 ++++++++++++++++ .../yawaflua.WebSockets.csproj | 7 ++++-- 11 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 yawaflua.WebSockets/Models/Interfaces/IWebSocket.cs diff --git a/Examples/ChatController.cs b/Examples/ChatController.cs index b621029..d248e6f 100644 --- a/Examples/ChatController.cs +++ b/Examples/ChatController.cs @@ -1,6 +1,6 @@ using yawaflua.WebSockets.Attributes; using yawaflua.WebSockets.Models.Abstracts; -using WebSocket = yawaflua.WebSockets.Core.WebSocket; +using yawaflua.WebSockets.Models.Interfaces; namespace Examples; @@ -9,7 +9,7 @@ public class ChatController : WebSocketController { public override async Task OnMessageAsync( - WebSocket webSocket, + IWebSocket webSocket, HttpContext httpContext) { await WebSocketManager.Broadcast(k => k.Path == "/chat", $"{webSocket.Client.Id}: {webSocket.Message}"); diff --git a/Examples/TestWebSocketServer.cs b/Examples/TestWebSocketServer.cs index 621e09f..fb9818d 100644 --- a/Examples/TestWebSocketServer.cs +++ b/Examples/TestWebSocketServer.cs @@ -1,8 +1,6 @@ -using System.Text.Json; -using Microsoft.AspNetCore.Mvc; -using yawaflua.WebSockets.Attributes; -using yawaflua.WebSockets.Core; +using yawaflua.WebSockets.Attributes; using yawaflua.WebSockets.Models.Abstracts; +using yawaflua.WebSockets.Models.Interfaces; namespace Examples; @@ -11,7 +9,7 @@ public class TestWebSocketServer : WebSocketController { [WebSocket("/sub-test")] - public override async Task OnMessageAsync(WebSocket webSocket, HttpContext httpContext) + public override async Task OnMessageAsync(IWebSocket webSocket, HttpContext httpContext) { await webSocket.SendAsync("Test! Now on it endpoint: " + WebSocketManager.GetAllClients().Count(k => k.Path == webSocket.Client.Path)); } diff --git a/README.md b/README.md index de4b84e..67f043e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ public class ChatController : WebSocketController { [WebSocket("/chat")] public override async Task OnMessageAsync( - WebSocket webSocket, + IWebSocket webSocket, HttpContext httpContext) { await webSocket.SendAsync("Message!"); @@ -58,7 +58,7 @@ public class NotificationsController : WebSocketController { [WebSocket("/notifications/{userId}")] public override async Task OnMessageAsync( - WebSocket webSocket, + IWebSocket webSocket, HttpContext httpContext) { var userId = httpContext.Request.RouteValues["userId"]; @@ -73,13 +73,13 @@ public class NotificationsController : WebSocketController public class GameController : WebSocketController { [WebSocket("join/{roomId}")] - public async Task JoinRoom(WebSocket webSocket, HttpContext context) + public async Task JoinRoom(IWebSocket webSocket, HttpContext context) { // Handle room joining } [WebSocket("leave/{roomId}")] - public async Task LeaveRoom(WebSocket webSocket, HttpContext context) + public async Task LeaveRoom(IWebSocket webSocket, HttpContext context) { // Handle room leaving } diff --git a/yawaflua.WebSockets.Tests/Core/WebSocketManagerTest.cs b/yawaflua.WebSockets.Tests/Core/WebSocketManagerTest.cs index 9bb9fdc..d903c81 100644 --- a/yawaflua.WebSockets.Tests/Core/WebSocketManagerTest.cs +++ b/yawaflua.WebSockets.Tests/Core/WebSocketManagerTest.cs @@ -11,6 +11,7 @@ using Moq; using Xunit; using yawaflua.WebSockets.Attributes; using yawaflua.WebSockets.Models.Abstracts; +using yawaflua.WebSockets.Models.Interfaces; using Assert = Xunit.Assert; using WebSocket = yawaflua.WebSockets.Core.WebSocket; using WebSocketManager = Microsoft.AspNetCore.Http.WebSocketManager; @@ -35,10 +36,10 @@ public class WebSocketRouterTests public class TestHandler : WebSocketController { [yawaflua.WebSockets.Attributes.WebSocket("/static")] - public static Task StaticHandler(WebSocket ws, HttpContext context) => Task.CompletedTask; + public static Task StaticHandler(IWebSocket ws, HttpContext context) => Task.CompletedTask; [yawaflua.WebSockets.Attributes.WebSocket("/instance")] - public Task InstanceHandler(WebSocket ws, HttpContext context) => Task.CompletedTask; + public Task InstanceHandler(IWebSocket ws, HttpContext context) => Task.CompletedTask; } [Fact] diff --git a/yawaflua.WebSockets/Core/WebSocket.cs b/yawaflua.WebSockets/Core/WebSocket.cs index 03f81dc..f4503dd 100644 --- a/yawaflua.WebSockets/Core/WebSocket.cs +++ b/yawaflua.WebSockets/Core/WebSocket.cs @@ -4,7 +4,7 @@ using yawaflua.WebSockets.Models.Interfaces; namespace yawaflua.WebSockets.Core; -public class WebSocket : IDisposable +internal class WebSocket : IWebSocket { private readonly System.Net.WebSockets.WebSocket _webSocket; private readonly WebSocketReceiveResult? _webSocketReceiveResult; @@ -16,7 +16,7 @@ public class WebSocket : IDisposable public string? CloseStatusDescription => _webSocket.CloseStatusDescription; public string? Message => _message; public WebSocketMessageType? MessageType => _webSocketReceiveResult?.MessageType; - public IWebSocketClient Client; + public IWebSocketClient Client { get; } internal WebSocket(System.Net.WebSockets.WebSocket webSocket, WebSocketReceiveResult? webSocketReceiveResult, string? message, IWebSocketClient client) { _webSocket = webSocket; diff --git a/yawaflua.WebSockets/Models/Abstracts/WebSocketController.cs b/yawaflua.WebSockets/Models/Abstracts/WebSocketController.cs index 04a2aa2..7af5ceb 100644 --- a/yawaflua.WebSockets/Models/Abstracts/WebSocketController.cs +++ b/yawaflua.WebSockets/Models/Abstracts/WebSocketController.cs @@ -7,9 +7,18 @@ namespace yawaflua.WebSockets.Models.Abstracts; public abstract class WebSocketController : IWebSocketController { + /// + /// WebsocketManager provides work with all clients + /// public IWebSocketManager WebSocketManager => new WebSocketManager(); - public virtual Task OnMessageAsync(WebSocket webSocket, HttpContext httpContext) + /// + /// Example of function OnMessage + /// + /// WebSocket with provided data about user e.t.c. + /// Http context of request + /// + public virtual Task OnMessageAsync(IWebSocket webSocket, HttpContext httpContext) { return Task.CompletedTask; } diff --git a/yawaflua.WebSockets/Models/Interfaces/IWebSocket.cs b/yawaflua.WebSockets/Models/Interfaces/IWebSocket.cs new file mode 100644 index 0000000..038daa2 --- /dev/null +++ b/yawaflua.WebSockets/Models/Interfaces/IWebSocket.cs @@ -0,0 +1,24 @@ +using System.Net.WebSockets; + +namespace yawaflua.WebSockets.Models.Interfaces; + +public interface IWebSocket : IDisposable +{ + WebSocketState State { get; } + WebSocketCloseStatus? CloseStatus { get; } + string? SubProtocol { get; } + string? CloseStatusDescription { get; } + string? Message { get; } + WebSocketMessageType? MessageType { get; } + IWebSocketClient Client { get; } + + Task SendAsync(string message, + WebSocketMessageType messageType = WebSocketMessageType.Text, + CancellationToken cancellationToken = default); + + Task CloseAsync(WebSocketCloseStatus closeStatus = WebSocketCloseStatus.NormalClosure, + string? reason = null, + CancellationToken cancellationToken = default); + + void Abort(); +} \ No newline at end of file diff --git a/yawaflua.WebSockets/Models/Interfaces/IWebSocketClient.cs b/yawaflua.WebSockets/Models/Interfaces/IWebSocketClient.cs index 3da8e4e..e1ffeaf 100644 --- a/yawaflua.WebSockets/Models/Interfaces/IWebSocketClient.cs +++ b/yawaflua.WebSockets/Models/Interfaces/IWebSocketClient.cs @@ -5,11 +5,33 @@ namespace yawaflua.WebSockets.Models.Interfaces; public interface IWebSocketClient { + /// + /// ID of user + /// public Guid Id { get; } + /// + /// Path, that user connects + /// public string Path { get; } + /// + /// Connection info + /// public ConnectionInfo? ConnectionInfo { get; } + /// + /// You can provides Items, like in auth middleware or any + /// public IDictionary? Items { get; set; } + /// + /// HttpRequest data + /// public HttpRequest? HttpRequest { get; } + /// + /// You should`nt use it, but, its full work with user + /// internal WebSocket webSocket { get; } + /// + /// Kick client + /// + /// null public Task Abort(); } \ No newline at end of file diff --git a/yawaflua.WebSockets/Models/Interfaces/IWebSocketController.cs b/yawaflua.WebSockets/Models/Interfaces/IWebSocketController.cs index 344ca9f..f5cec8b 100644 --- a/yawaflua.WebSockets/Models/Interfaces/IWebSocketController.cs +++ b/yawaflua.WebSockets/Models/Interfaces/IWebSocketController.cs @@ -5,5 +5,11 @@ namespace yawaflua.WebSockets.Models.Interfaces; internal interface IWebSocketController { - Task OnMessageAsync(WebSocket webSocket, HttpContext httpContext); + /// + /// Example of working with IWebSocketController + /// + /// + /// + /// + Task OnMessageAsync(IWebSocket webSocket, HttpContext httpContext); } \ No newline at end of file diff --git a/yawaflua.WebSockets/Models/Interfaces/IWebSocketManager.cs b/yawaflua.WebSockets/Models/Interfaces/IWebSocketManager.cs index 9857fbf..1450161 100644 --- a/yawaflua.WebSockets/Models/Interfaces/IWebSocketManager.cs +++ b/yawaflua.WebSockets/Models/Interfaces/IWebSocketManager.cs @@ -5,7 +5,28 @@ namespace yawaflua.WebSockets.Models.Interfaces; public interface IWebSocketManager { + /// + /// Broadcast message to all users + /// + /// selector of users + /// message, broadcasted to all users + /// type of message + /// cancellation token + /// public Task Broadcast(Func selector,string message, WebSocketMessageType messageType = WebSocketMessageType.Text, CancellationToken cts = default); + /// + /// Provides list of clients connected to host + /// + /// public List GetAllClients(); + /// + /// Send to specific user data + /// Analog of Broadcast(k => k.Id == ID, message) + /// + /// Id of user + /// message to user + /// type of message + /// cancellation token + /// public Task SendToUser(Guid id, string message, WebSocketMessageType messageType, CancellationToken cts); } \ No newline at end of file diff --git a/yawaflua.WebSockets/yawaflua.WebSockets.csproj b/yawaflua.WebSockets/yawaflua.WebSockets.csproj index d4f25f2..a91d617 100644 --- a/yawaflua.WebSockets/yawaflua.WebSockets.csproj +++ b/yawaflua.WebSockets/yawaflua.WebSockets.csproj @@ -4,15 +4,18 @@ net6.0;net7.0;net8.0;net9.0 enable enable - 1.0.0 + 0.0.9 yawaflua.WebSockets New AspNet controllers looks like websocket manager Dmitrii Shimanskii https://github.com/yawaflua/WebSockets - https://github.com/yawaflua/WebSockets/LICENCE https://github.com/yawaflua/WebSockets + https://github.com/yawaflua/WebSockets websocket true + true + LICENSE + README.md