Node.js上でWebSocketを用いてサーバと接続する際に以下の不正リクエストエラーが帰ってくる場合の原因の一例についてのメモです。
HTTP/1.1 400 Bad Request
RFC 6455 - The WebSocket Protocol
RFC 6455によるとWebSocketはリクエストのパラメータとして以下のようになっています。
リクエストに必要なパラメータ
- GET /ws HTTP/1.1\r\n
- Host: 192.168.12.145:22300\r\n
- Upgrade: websocket\r\n
- Connection: Upgrade\r\n
- Sec-WebSocket-Version: 13\r\n
- Sec-WebSocket-Key: ZQ0ZM3WA2Yqpb6Ne7d10iA==\r\n
オプション
- Origin: chrome---extension://pfdhoblngboilpfeibdedpjgfnlcodoo\r\n
- Sec-WebSocket-Extensions: permessage-deflate;client_max_window_bits\r\n
原因
WiresharkでNode.jsのクライアント側から送ったパケットを見てみると
- GET /ws HTTP/1.1\r\n
- Host: 192.168.12.145:22300\r\n
- Upgrade: websocket\r\n
- Connection: Upgrade\r\n
- Sec-WebSocket-Version: 13\r\n
- Sec-WebSocket-Key: ZQ0ZM3WA2Yqpb6Ne7d10iA==\r\n
であり、必要なパラメータは網羅しています。
ここでオプションを見てみるとOriginはブラウザクライアントの場合は必要であるとなっています( RFC 6455: 4.2.1. Reading the Client's Opening Handshake )。
今回はサーバ側がOrigin必須であるブラウザクライアントを想定して立てられたものである可能性が考えられます。
解決策
Originに適当な要素を与えることによって不正リクエストではなくなります。
Node.jsのwebsocketパッケージを使用して記述すると以下のようになります。
var WebSocketClient = require('websocket').client;
var ws = new WebSocketClient();
var origin = "適当なクライアント名”;
ws.connect('ws://192.168.12.145:22300/ws',null,[origin]);