WebSocket đã sẵn sàng để test!


Sau 3 tuần thì Websocket middleware đã sẵn sàng. Phần khó nhất khi viết module này là làm sao xử lý request từ dạng request/response sang 1 socket cho phép gửi/nhận bất kỳ dạng dữ liệu nào. Nếu các bạn có theo dõi các commit ban đầu thì sẽ thấy mình đã phải thử một số cách khác nhau để chọn ra cách cuối cùng.

Giải pháp mình đưa ra là cung cấp một IWebSocketManager cho IMiniAppContext, IWebSocketManager mặc nhiên sẽ luôn trả về false khi gọi đến IsUpgradeRequest, và throw một InvalidOperationException nếu gọi đến AcceptAsync.

Khi các bạn thêm WebSocket middleware (gọi services.AddWebSocketService() và appBuilder.UseWebSockets()), nó sẽ theo dõi request và kiểm tra xem request đó có phải là một yêu cầu nâng cấp HTTP request lên websocket request không, nếu đúng là vậy thì nó sẽ thay thế IWebSocketManager mặc nhiên với DefaultWebSocketManager, DefaultWebSocketManager sẽ có nhiệm vụ gửi lại response cho client thông báo chấp nhận kết nối và đồng thời tạo một WebSocket cho phép app của bạn tương tác với client.

Nói thêm một chút về websocket, đây là một giao thức cho phép client và server nói chuyện với nhau dạng duplex, tức là hai bên có thể gửi nhận cho nhau như socket thông thường chứ không theo cơ chế request/response. Một kết nối websocket sẽ luôn bắt đầu như một GET request (HTTP/2 có hỗ trợ thêm CONNECT), với một vài header đặc biệt:

Upgrade: websocket

Sec-WebSocket-Key: <clientkey>

Sec-WebSocket-Version: 13

Sec-WebSocket-Extensions: … (header này là tùy chọn)

(clientkey được sinh ngẫu nhiên và biến đổi theo một vài quy tắc cho trước)

Đây được gọi là yêu cầu nâng cấp từ một kết nối thông thường thành một kết nối websocket. Nếu server đồng ý nó sẽ trả lại code 101 và một số header:

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: <serverkey>

(xem hình 3, https://github.com/…/WebSocket/DefaultWebSocketManager.cs)

Serverkey được tạo ra từ <clientkey> với một công thức bí mật 😁.

Sau response này kết nối sẽ chuyển qua dạng websocket.

Các bạn có thể dùng Postman để nối vào wss://www.mini-web-server.com/chatserver (như trong hình 1), nhớ là Add request dạng websocket nhé.

Cách viết phần hander cho chatserver có thể xem trong hình 2.

Happy websocketing!

Leave a comment