انجیناکس؛ شب ۲۶: WebSocket و تبادل واقعی پیام
فهرست نوشته
WebSocket پس از handshake یک ارتباط دوطرفهٔ طولانی میسازد. امشب echo server را از wss منتشر میکنیم و تنها به دریافت کد 101 اکتفا نمیکنیم.
این جلسه بخشی از دورهٔ انجیناکس در ۵۰ شب است. قرارداد آزمایشگاه، مسیرها و روال اعمال تغییر در راهنمای دوره آمده است.
محیط: app، Python حداقل 3.10 طبق LAB_PYTHON؛ مرورگر با اعتماد CA در profile آزمایشگاهی و نام app به IP وبسرور نگاشتشده.
برنامهٔ echo#
"$LAB_PYTHON" -m venv ~/nginx-lab/ws-venv
~/nginx-lab/ws-venv/bin/python -m pip install websockets
~/nginx-lab/ws-venv/bin/python -m pip freeze > ~/nginx-lab/ws-requirements.txt
فایل ws.py:
import asyncio
from websockets.asyncio.server import serve
async def echo(ws):
async for msg in ws:
await ws.send(msg)
async def main():
async with serve(echo, "127.0.0.1", 8765, origins=["https://app.nginx.test"]):
await asyncio.get_running_loop().create_future()
asyncio.run(main())
با Python همان venv اجرا کن. در http:
map $http_upgrade $lab_connection {
default upgrade;
'' close;
}
در app:
location /ws/ {
proxy_pass http://127.0.0.1:8765;
proxy_http_version 1.1;
include /etc/nginx/snippets/lab-proxy-headers.conf;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $lab_connection;
proxy_read_timeout 60s;
}
Upgrade و Connection هدرهای hop-by-hop هستند و باید صریحاً برای backend تنظیم شوند. مسیر خاص از location / جدا انتخاب میشود؛ backend باید مسیر و Origin را بپذیرد.
پیام و مبدأ#
در console صفحهٔ HTTPS app:
const ws = new WebSocket("wss://app.nginx.test/ws/");
ws.onmessage = event => console.log(event.data);
ws.onopen = () => ws.send("nginx lab ping");
باید همان پیام برگردد. اتصال از صفحهٔ Origin نامجاز باید رد شود؛ Origin جای احراز هویت نیست. heartbeat، قطع backend و reconnect را هم بسنج. HTTP/2 صفحه به معنی خودکار بودن WebSocket روی HTTP/2 یا پشتیبانی Socket.IO نیست.
بازگشت: location و map بلااستفاده را بردار و برنامه را متوقف کن؛ nginx -t و پاسخ app عادی را دوباره بررسی کن.
منبع: WebSocket proxy ، سرور websockets .