0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

nginx をリバースプロキシにして WebSocket を扱いたい時

0
Posted at

はじめに

nginx をリバースプロキシにして、バックエンドのサーバーと WebSocket で通信しようとすると、接続が確立できずエラーになることがあります。

私は、最近 nginx をリバースプロキシに Vite の開発環境を構築していた際にこの現象に遭遇しました。
Vite は HMR するために WebSocket を用いているので、nginx の設定が不十分だと、コードを変更して保存してもブラウザ側にリアルタイムで反映されない状態になります。
おそらく、コンソール画面に以下のようなエラーが出力されるはずです。

スクリーンショット 2026-02-28 21.12.20.png

調べてみた感じ、nginx で WebSocket 通信をしようとすると、追加で設定が必要だったので、それについてまとめます。

エラー内容

以下のように、ws を使って nginx をリバースプロキシに、WebSocket 通信を待ち受けるサーバーを構築してみます。

import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ port: 3000 });

wss.on('connection', (ws) => {
  ws.on('error', console.error);

  ws.on('message', (data) => {
    console.log('received: %s', data);
  });

  ws.send('example');
})
server {
    listen 80;
    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

websocat を WebSocket client として利用し、WebSocket 通信をしようとすると、以下のようなエラーが出力されます。

$ websocat ws://localhost:80
websocat: WebSocketError: WebSocketError: Received unexpected status code (426 Upgrade Required)
websocat: error running

426 Upgrade Required

The HTTP 426 Upgrade Required client error response status code indicates that the server refused to perform the request using the current protocol but might be willing to do so after the client upgrades to a different protocol.

現在のプロトコルではリクエストを実行できないが、プロトコルをアップグレードすれば受け付ける可能性があることを示すステータスコードです。

426 Upgrade Required が出力される理由

WebSocket 通信は、HTTP1.1 のリクエストの送信後に、プロトコルを切り替えることによって実現されています。

このプロトコルの切り替えは、クライアントからのリクエストヘッダーに含まれる UpgradeConnection を確認することによって行われます。( https://datatracker.ietf.org/doc/html/rfc6455#section-4.1

nginx をリバースプロキシとして動かす場合、デフォルトではこれらのヘッダーがバックエンドのサーバーへ転送されないようになっています。
これは Hop-by-hop という、HTTPプロキシが転送先へ渡してはいけない HTTP ヘッダーが定められていて、nginx がその仕様に則っているためです。

ということで、nginx をリバースプロキシにして WebSocket 通信を行おうとすると、本来必要なヘッダーが削除されてしまうため、バックエンドのサーバーに正しくリクエストが転送されず WebSocket 通信を開始できないため 426 が返されるということになります。

対応方法

UpgradeConnection を正しく転送できるようにすればいいので、以下のように設定ファイルを少し変更するだけで、対応することができます。

server {
    listen 80;
    location / {
+       proxy_set_header Upgrade $http_upgrade;
+       proxy_set_header Connection "upgrade";
+       proxy_http_version 1.1;

        proxy_pass http://127.0.0.1:3000;
    }
}

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?