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 .