Cabeçalhos HTTP na API do cliente Websockets

Parece que é fácil adicionar headers HTTP personalizados ao seu cliente websocket com qualquer cliente de header HTTP que suporte isso, mas não consigo encontrar como fazer isso com a API JSON.

No entanto, parece que deve haver suporte a esses headers na especificação .

Alguém tem uma pista sobre como alcançá-lo?

var ws = new WebSocket("ws://example.com/service"); 

Especificamente, eu preciso ser capaz de enviar um header de autorização HTTP.

Atualizada

Resposta curta: não, mas funciona a autenticação básica

Resposta mais longa:

Não há nenhum método na API JavaScript WebSockets para especificar headers adicionais para o cliente / navegador para enviar. No entanto, o caminho HTTP (“GET / xyz”), header de autenticação básica (“Autorização”) e header de protocolo (“Sec-WebSocket-Protocol”) podem ser especificados no construtor WebSocket.

O header de autorização é gerado a partir do campo nome de usuário e senha (ou apenas nome de usuário) do URI WebSocket:

 var ws = new WebSocket("ws://username:password@example.com") 

Os resultados acima resultam no seguinte header com a string “username: password” base64 codificada:

 Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= 

Eu testei a autenticação básica no Chrome 55 e no Firefox 50 e verifiquei que as informações básicas de autenticação são de fato negociadas com o servidor (isso pode não funcionar no Safari).

O header Sec-WebSocket-Protocol (que às vezes é estendido para ser usado na autenticação específica do websocket) é gerado a partir do segundo argumento opcional para o construtor WebSocket:

 var ws = new WebSocket("ws://example.com/path", "protocol"); var ws = new WebSocket("ws://example.com/path", ["protocol1", "protocol2"]); 

Os resultados acima nos seguintes headers:

 Sec-WebSocket-Protocol: protocol 

e

 Sec-WebSocket-Protocol: protocol1, protocol2 

Obrigado ao Dmitry Frank pela resposta básica do auth

O problema do header de autorização HTTP pode ser tratado com o seguinte:

 var ws = new WebSocket("ws://username:password@example.com/service"); 

Em seguida, um header HTTP de autorização básica apropriado será definido com o username e a password fornecidos. Se você precisar de autorização básica, então está tudo pronto.


Eu quero usar Bearer no entanto, e eu recorri ao seguinte truque: Eu conecto ao servidor da seguinte forma:

 var ws = new WebSocket("ws://my_token@example.com/service"); 

E quando meu código no lado do servidor recebe o header de Autorização Básica com nome de usuário não vazio e senha vazia, ele interpreta o nome de usuário como um token.

Você não pode adicionar headers, mas, se você só precisa passar valores para o servidor no momento da conexão, você pode especificar uma parte da string de consulta na url:

 var ws = new WebSocket("ws://example.com/service?key1=value1&key2=value2"); 

Esse URL é válido, mas – é claro – você precisará modificar o código do servidor para analisá-lo.

Você não pode enviar o header personalizado quando quiser estabelecer uma conexão WebSockets usando a API JavaScript WebSockets. Você pode usar headers Subprotocols usando o segundo construtor de class WebSocket:

 var ws = new WebSocket("ws://example.com/service", "soap"); 

e então você pode obter os headers Subprotocols usando a chave Sec-WebSocket-Protocol no servidor.

Existe também uma limitação, os valores dos headers Subprotocols não podem conter uma vírgula ( , )!

Mais de uma solução alternativa, mas todos os navegadores modernos enviam os cookies de domínio junto com a conexão, portanto, usando:

 var authToken = 'R3YKZFKBVi'; document.cookie = 'X-Authorization=' + authToken + '; path=/'; var ws = new WebSocket( 'wss://localhost:9000/wss/' ); 

Terminar com os headers de conexão de solicitação:

 Cookie: X-Authorization=R3YKZFKBVi 

Tecnicamente, você estará enviando esses headers através da function de conexão antes da fase de atualização do protocolo.

 var WebSocketClient = require('websocket').client; var ws = new WebSocketClient(); ws.connect(url, '', headers); 

Totalmente hackeado assim, graças à resposta de kanaka.

Cliente:

 var ws = new WebSocket( 'ws://localhost:8080/connect/' + this.state.room.id, store('token') || cookie('token') ); 

Servidor (usando Koa2 neste exemplo, mas deve ser semelhante em qualquer lugar):

 var url = ctx.websocket.upgradeReq.url; // can use to get url/query params var authToken = ctx.websocket.upgradeReq.headers['sec-websocket-protocol']; // Can then decode the auth token and do any session/user stuff...