簡體   English   中英

Laravel 網絡套接字與 nginx

[英]Laravel websockets with nginx

I have followed tutorials to configure laravel with websockets using docker, except that my php version is PHP 8.1.9, and laravel 8.

我的 nginx 容器是 web_dev 容器的反向代理,並執行 SSL 終止。 所以內部進一步的通信是通過 http。

nginx.conf

server {
    listen        80;
    server_name   mydomain.co.uk *.mydomain.co.uk;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen        443 ssl;
    server_name   mydomain.co.uk *.mydomain.co.uk;

    include       common.conf;
    include       ssl.conf;

    location / {
        include     common_location.conf;
        proxy_pass  http://web_dev;
    }
}

server {
    listen        6001 ssl;
    server_name   mydomain.co.uk *.mydomain.co.uk;

    include       common.conf;
    include       ssl.conf;
        
    location /ws {
        proxy_read_timeout     60;
        proxy_connect_timeout  60;
        proxy_redirect         off;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
        proxy_set_header    Sec-WebSocket-Key       'SGVsbG8sIHdvcmxkIQAAAA==';
        proxy_set_header    Sec-WebSocket-Version   '13';

        include            common_location.conf;
        proxy_pass         http://web_dev:6001/;
    }
}

然后我有一個 curl 命令:

curl -k \
    --no-buffer \
    --header "Connection: upgrade" \
    --header "Upgrade: websocket" \
    -v \
    https://mydomain.co.uk:6001/ws/app/mydomainkey

這是 output:

Connected to mydomain.co.uk (127.0.0.1) port 6001 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
  ....
* TLSv1.2 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /ws/app/mydomainkey HTTP/1.1
> Host: mydomain.co.uk:6001
> User-Agent: curl/7.81.0
> Accept: */*
> Connection: upgrade
> Upgrade: websocket
> 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 101 Switching Protocols
< Server: nginx/1.21.5
< Date: Sun, 04 Sep 2022 12:00:33 GMT
< Connection: upgrade
< Upgrade: websocket
< Sec-WebSocket-Accept: 5Tz1rM6Lpj3X4PQub3+HhJRM11s=
< X-Powered-By: Ratchet/0.4.4
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
�r{"event":"pusher:connection_established","data":"{\"socket_id\":\"155833011.137698690\",\"activity_timeout\":30}"}

我認為這表明端口 6001 和 SSL 配置正確,並且 websocket 連接已建立。

當我 go 到 url 的 websockets 儀表板並單擊連接時,我得到

WebSocket connection to 'wss://mydomain.co.uk:6001/ws/app/bookhaircut?protocol=7&client=js&version=4.3.1&flash=false' failed:

在此處輸入圖像描述

我也試過fetch("wss://mydomain.co.uk:6001/ws/app/mydomainkey?protocol=7&client=js&version=4.3.1&flash=false"); 這給出了一個不同的錯誤:

在此處輸入圖像描述

在 web_dev 容器上,我正在運行運行php artisan websockets:serve的主管。 我可以驗證我的 web_dev 容器可以連接到它的 websockets 運行服務,因為我在php artisan tinker中運行:

`event (new \App\Events\NewTrade('test'))`
=> []

然后我檢查了主管日志,我得到了很多條目: 在此處輸入圖像描述

所以總而言之:

  1. nginx 服務正常,因為 curl 命令與 nginx 和 ZEA52C36203C5F99C3CE2442D 一起正常工作
  2. laravel 內部連接正確
  3. 但是 web 瀏覽器中的 pusher-js 抱怨不支持 wss 方案並且 websocket 連接失敗。 我的 nginx 版本:nginx/1.21.5
  4. 我什至還沒有使用 Echo。 Echo 使用 pusher-js,儀表板使用 pusher-js 實現。 因此,如果儀表板不起作用,我的 Echo 也不會起作用。
  5. 我現在在 package.json 中將我的推送器降級為 4.3.1 但這並沒有做任何事情,因為該版本在儀表板中是硬編碼的(雖然也是 4.3)。

在此處輸入圖像描述

有任何想法嗎?

  1. 我試圖修改儀表板以拉出不同的版本https://cdnjs.cloudflare.com/ajax/libs/pusher/6.0.3/pusher.js這沒有任何區別。

  2. nginx 能否支持 wss 而不是 http? 我只見過 http 的配置。 使用 wss 進行配置:拋出錯誤。

所以我沒有想法。

這是我的配置文件:

websockets.php

'apps' => [
    [
        'id' => env('PUSHER_APP_ID'),
        'name' => env('APP_NAME'),
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'path' => "/ws",
        'capacity' => null,
        'enable_client_messages' => false,
        'enable_statistics' => true,
    ],
],

/* ssl is left empty.*/

相關問題:

我是如何發現的:

I first tried to set SSL cert for the internal communication despite nginx doing termination (I had to try it) - but then the curl command broke, I couldn't connect to my websockets unless I removed my SSL certificates (was getting bad gateway) .

所以我最終得到了這些:

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'encrypted' => false,
        'host' => "127.0.0.1",
        'port' => 6001,
        'useTLS' => false,
        'scheme' => 'http',
    ],
],

在 config/websockets.php

'apps' => [
    [
        'id' => env('PUSHER_APP_ID'),
        'name' => env('APP_NAME'),
        'key' => env('PUSHER_APP_KEY'),
        'secret' => env('PUSHER_APP_SECRET'),
        'path' => "/ws",    //<-- important for nginx path detection
        'capacity' => null,
        'enable_client_messages' => false,
        'enable_statistics' => true,
    ],
],
'ssl' => [
    'local_cert' => null,
    'local_pk' => null,
    'passphrase' => null,
],

然后我注意到關於日志記錄的一件事。 當我在瀏覽器中收到 websocket 錯誤時,我還收到了我的 supervisor/websocket.log 的新日志條目。

我試圖刪除'path' => "/ws" ,我收到了相同的瀏覽器錯誤,但沒有日志條目。

當有總比沒有好時,這給了我第一個提示。 而且我需要堅持任何不會破壞此日志記錄功能的設置。

然后我發現當我從nginx.conf中刪除這些行時,它開始一切正常,令人震驚!

    proxy_set_header    Sec-WebSocket-Key       'SGVsbG8sIHdvcmxkIQAAAA==';
    proxy_set_header    Sec-WebSocket-Version   '13';

最初我添加這些是為了簡化 curl 命令。 但我不知道這會破壞瀏覽器的 websocket。 所以用於測試的 curl 現在看起來像這樣:

curl -k \
    --no-buffer \
    --header "Connection: upgrade" \
    --header "Upgrade: websocket" \
    --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQAAAA==" \ //<-- this is random you can use it
    --header "Sec-WebSocket-Version: 13" \
    -v \
    https://mydomain.co.uk:6001/ws/app/mydomainkey

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM