Skip to content

Código de status HTTP · Informativos (1xx)

101 Switching Protocols

O 101 Switching Protocols significa que o servidor aceitou o pedido de Upgrade do cliente e a conexão passa a falar outro protocolo. Na prática ele aparece toda vez que o navegador abre um WebSocket: o 101 é o fim bem-sucedido do aperto de mão, não um erro.

Dados sobre este código de status
Classe1xx, Informativos
Definido emRFC 9110 §15.2.2
Pode ir para o cache por padrãoNão
Pode repetir o pedidoNão se aplica; depois do 101 a conexão passa a falar o novo protocolo
Cabeçalhos relevantes
  • Upgrade: obrigatório no 101; indica o protocolo que passa a valer, por exemplo websocket
  • Connection: precisa listar Upgrade para os intermediários saberem que o cabeçalho é salto a salto
  • Sec-WebSocket-Accept: só em WebSocket: prova que o servidor leu a chave do cliente (RFC 6455)

O que significa o 101

A RFC 9110, seção 15.2.2, exige que o servidor inclua um cabeçalho Upgrade com o protocolo que assume a conexão. No WebSocket (RFC 6455) o navegador envia Upgrade: websocket, Connection: Upgrade e uma Sec-WebSocket-Key aleatória; o servidor responde 101 com Sec-WebSocket-Accept, um hash dessa chave. Depois da linha em branco que encerra o 101, não passa mais HTTP naquela conexão TCP.

O mecanismo é do HTTP/1.1. O HTTP/2 não usa o 101 (RFC 9113, seção 8.6), e WebSockets sobre HTTP/2 usam um CONNECT estendido (RFC 8441). Por isso um proxy reverso precisa falar HTTP/1.1 com o backend para o upgrade passar.

Quando usar

  • Deixe a biblioteca de WebSocket enviar; escrever o aperto de mão na mão exige calcular o Sec-WebSocket-Accept e é fácil errar.
  • Coloque o endpoint de WebSocket num caminho próprio (/ws) para que as regras de upgrade do proxy valham só ali.

Causas comuns

Se você está visitando o site

  • Um chat, placar ao vivo ou painel nunca atualiza: um proxy corporativo, VPN ou antivírus está bloqueando upgrades de WebSocket na sua rede.

Se você administra o servidor

  • O aperto de mão volta 200, 400 ou 404 em vez de 101: o nginx ou outro proxy descartou os cabeçalhos Upgrade e Connection, que são salto a salto e não são repassados por padrão.
  • O socket abre com 101 e cai depois de exatos 60 segundos sem tráfego: o nginx fecha conexões ociosas após o proxy_read_timeout, que é 60s por padrão.

Como resolver

Se você está visitando o site

  • Teste outra rede ou desative a VPN ou a inspeção HTTPS do antivírus e recarregue a página.

Se você administra o servidor

  • No nginx, defina proxy_http_version 1.1 e repasse Upgrade e Connection de forma explícita, como no exemplo abaixo.
  • Envie frames de ping a cada 20 ou 30 segundos, ou aumente o proxy_read_timeout no location do /ws.

Como enviar um 101

Route handlers do Next.js não conseguem assumir o socket, então não respondem a um upgrade; rode o servidor de WebSocket como processo separado ou num servidor customizado.

Express (Node.js)
import { WebSocketServer } from 'ws';

const server = app.listen(3000);
const wss = new WebSocketServer({ noServer: true });

// ws writes "101 Switching Protocols" and Sec-WebSocket-Accept for you
server.on('upgrade', (req, socket, head) => {
  if (req.url !== '/ws') return socket.destroy();
  wss.handleUpgrade(req, socket, head, (ws) => {
    ws.send('connected');
  });
});
Go net/http
// github.com/gorilla/websocket
var upgrader = websocket.Upgrader{}

mux.HandleFunc("GET /ws", func(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil) // sends 101 Switching Protocols
	if err != nil {
		return // Upgrade already wrote an HTTP error response
	}
	defer conn.Close()
	conn.WriteMessage(websocket.TextMessage, []byte("connected"))
})
Python FastAPI
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def ws_endpoint(websocket: WebSocket):
    await websocket.accept()  # the server sends 101 Switching Protocols
    await websocket.send_text("connected")
Nginx
location /ws {
  proxy_pass http://app;
  proxy_http_version 1.1;               # 101 only exists in HTTP/1.1
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_read_timeout 1h;                # default 60s kills idle sockets
}

Costuma ser confundido com

101 vs 426
O 426 Upgrade Required é o servidor exigindo a troca de protocolo; o 101 é o servidor aceitando uma troca pedida pelo cliente.
101 vs 200
Um 200 no aperto de mão do WebSocket indica que algo ignorou o Upgrade e serviu uma página normal, então o socket falha.

Perguntas frequentes

Status 101 na aba Rede do navegador é erro?
Não. Uma linha de WebSocket com status 101 indica que o aperto de mão deu certo. As mensagens trocadas depois aparecem nessa mesma linha, na aba Mensagens ou Resposta, conforme o navegador.
Por que meu WebSocket recebe 200 ou 400 em vez de 101?
Quase sempre um proxy reverso não está repassando os cabeçalhos Upgrade e Connection, e o backend recebe um GET comum. No nginx, inclua proxy_http_version 1.1 e as duas linhas proxy_set_header para Upgrade e Connection.
O HTTP/2 usa o 101 Switching Protocols?
Não. A RFC 9113 diz que o HTTP/2 não usa o 101. WebSockets sobre HTTP/2 abrem com um CONNECT estendido, definido na RFC 8441, e muitos servidores simplesmente mantêm o WebSocket em HTTP/1.1.

Revisado em por Arielton Oberek.