Skip to content

Código de status HTTP · Redirecionamento (3xx)

300 Multiple Choices

O status 300 Multiple Choices indica que o recurso tem mais de uma representação, como o mesmo documento em formatos ou idiomas diferentes, e o servidor quer que o cliente escolha. Na prática ele quase só aparece em configurações de negociação de conteúdo, como o MultiViews do Apache, quando nenhuma variante ganha das outras.

Dados sobre este código de status
Classe3xx, Redirecionamento
Definido emRFC 9110 §15.4.1
Pode ir para o cache por padrãoSim, de forma heurística
Pode repetir o pedidoEscolha uma das alternativas listadas, ou siga o Location se o servidor enviou um
Cabeçalhos relevantes
  • Location: opcional: a opção preferida pelo servidor, que o cliente pode seguir sozinho
  • Link: uma forma de listar as alternativas, com rel="alternate"

O que significa o 300

A RFC 9110, seção 15.4.1, descreve o 300 como negociação reativa: em vez de escolher uma representação, o servidor lista as alternativas e deixa o usuário ou o cliente seguir a que preferir. Se o servidor tiver uma favorita, deve indicá-la no cabeçalho Location, e o cliente pode segui-la automaticamente.

A especificação nunca definiu um formato para essa lista, então o navegador só mostra o corpo da resposta e deixa a escolha para quem está lendo. Por isso o código é raro: a negociação proativa, em que o servidor lê Accept e Accept-Language e decide sozinho, venceu em quase todo lugar. Ao contrário da maioria dos 3xx, o 300 pode ser guardado em cache de forma heurística.

Quando usar

  • Só quando o servidor realmente não consegue decidir e a escolha humana é aceitável, por exemplo um conjunto de dados oferecido em CSV, JSON e Parquet para um cliente que não mandou um Accept útil.
  • Envie um Location com a variante preferida, para que clientes que seguem sozinhos caiam em algo razoável, e uma lista curta em HTML ou JSON com as alternativas no corpo.

Causas comuns

Se você administra o servidor

  • O mod_negotiation do Apache com Options +MultiViews encontra vários arquivos que servem igualmente bem, como relatorio.en.html e relatorio.pt.html, e responde 300 com uma lista em vez de escolher.

Como resolver

Se você está visitando o site

  • Clique na versão que você quer na lista mostrada pela página; o servidor está esperando essa escolha.

Se você administra o servidor

  • Adicione ForceLanguagePriority Prefer Fallback com uma lista em LanguagePriority para o Apache servir uma variante, ou desligue o MultiViews e use URLs explícitas.
  • Em APIs, negocie pelo Accept e responda 200 com o formato escolhido, ou 406 quando nenhum servir.

Como enviar um 300

Express (Node.js)
app.get('/datasets/:name', (req, res) => {
  res.set('Location', '/datasets/sales.csv');
  res.status(300).json({ choices: ['/datasets/sales.csv', '/datasets/sales.json', '/datasets/sales.parquet'] });
});
Next.js App Router (route handler)
// app/datasets/[name]/route.ts
export async function GET() {
  return Response.json(
    { choices: ['/datasets/sales.csv', '/datasets/sales.json', '/datasets/sales.parquet'] },
    { status: 300, headers: { 'Location': '/datasets/sales.csv' } }
  );
}
Go net/http
mux.HandleFunc("GET /datasets/{name}", func(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Location", "/datasets/sales.csv")
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusMultipleChoices) // 300
	w.Write([]byte(`{"choices":["/datasets/sales.csv","/datasets/sales.json","/datasets/sales.parquet"]}`))
})
Python FastAPI
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

@app.get("/datasets/{name}")
def get_dataset(name: str):
    return JSONResponse(status_code=300, content={"choices": ["/datasets/sales.csv", "/datasets/sales.json", "/datasets/sales.parquet"]}, headers={"Location": "/datasets/sales.csv"})

Costuma ser confundido com

300 vs 406
O 406 Not Acceptable diz que nenhuma representação atende ao que o cliente pediu; o 300 diz que várias servem e o cliente deve escolher.
300 vs 302
O 302 aponta para uma única outra URL; o 300 oferece um cardápio delas.

Perguntas frequentes

O navegador segue um 300 Multiple Choices sozinho?
Só quando a resposta traz um cabeçalho Location, e mesmo assim depende do cliente. Sem Location, o navegador mostra o corpo como uma página comum, então ele precisa ter links clicáveis para cada alternativa.
Por que o Apache responde 300 Multiple Choices?
A negociação de conteúdo do MultiViews achou vários arquivos para o nome pedido com a mesma pontuação frente aos cabeçalhos da requisição. O ForceLanguagePriority Prefer faz o Apache escolher um pela LanguagePriority em vez de perguntar.
Uma API REST deve usar 300 Multiple Choices?
Quase nunca. APIs costumam negociar pelo cabeçalho Accept e responder 200 no formato escolhido, ou 406 quando nada serve. Um 300 obriga cada cliente a implementar uma etapa de escolha que nenhum padrão descreve.

Revisado em por Arielton Oberek.