Skip to content

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

308 Permanent Redirect

O status 308 Permanent Redirect significa que o recurso mudou de vez para a URL do Location e o cliente deve repetir o pedido lá com o mesmo método e corpo. É a versão permanente do 307 e a escolha segura para mudar endpoints de API ou qualquer URL que receba POST.

Dados sobre este código de status
Classe3xx, Redirecionamento
Definido emRFC 9110 §15.4.9
Pode ir para o cache por padrãoSim, de forma heurística
Pode repetir o pedidoRepita o mesmo pedido no Location e use essa URL daqui em diante
Cabeçalhos relevantes
  • Location: a nova URL definitiva; método e corpo vão para lá sem mudança
  • Cache-Control: como o 301, fica no cache do navegador salvo instrução em contrário

O que significa o 308

O 308 foi criado pela RFC 7238 em 2014, virou Proposed Standard com a RFC 7538 em 2015 e hoje está na RFC 9110, seção 15.4.9. Ele tem o mesmo sentido do 301, uma nova URI permanente, mas proíbe a troca de POST por GET que os navegadores aplicam ao 301. Pode ir para o cache de forma heurística, então o navegador lembra dele como lembra de um 301.

O Google trata o 308 exatamente como o 301, um sinal forte de que o destino deve virar a URL canônica. O Next.js envia 308 por padrão nos redirects do next.config com permanent: true, no permanentRedirect() e na normalização de trailingSlash, então muitos sites emitem 308 sem nunca terem escolhido.

Todos os navegadores atuais e as bibliotecas HTTP mais usadas seguem o 308. A única lacuna antiga era o Internet Explorer 11 no Windows 7 e 8.1, que não entendia o código; se você ainda atende esses clientes, o 301 é a escolha conservadora para páginas acessadas com GET.

Quando usar

  • Mudar de vez uma versão ou endpoint de API, como /api/v1/upload para /api/v2/upload, enquanto os clientes continuam mandando POST.
  • Redirecionamentos de host canônico ou para HTTPS em sites que também recebem formulários ou webhooks.
  • Qualquer lugar onde você usaria 301 mas precisa manter o método e o corpo.

Causas comuns

Se você está visitando o site

  • ERR_TOO_MANY_REDIRECTS causado por uma regra 308 de barra ou de host brigando com outra regra; como o navegador guarda o 308, o loop pode continuar depois que o servidor foi corrigido.

Se você administra o servidor

  • O trailingSlash do Next.js (ou um redirect com permanent: true) discordando de uma regra da CDN ou do proxy que coloca ou tira a barra no sentido contrário.
  • Remetentes de webhook e clientes de API ainda chamando um endpoint antigo: o 308 mantém os clientes bem-comportados funcionando, mas alguns clientes HTTP não seguem redirecionamento em POST e registram o 308 como falha.
  • Corpos enviados em streaming: o fetch() não consegue reenviar um corpo que era um ReadableStream, então um upload que encontra um 308 (ou um 307) falha em vez de ser redirecionado.

Como resolver

Se você está visitando o site

  • Limpe os arquivos em cache do site para descartar um 308 antigo, ou teste a página numa janela anônima.

Se você administra o servidor

  • Mapeie a cadeia com curl -sIL e faça as regras de barra e de host concordarem, aplicadas em uma única camada.
  • Peça aos remetentes de webhook para atualizar a URL e mantenha o 308 até o tráfego para o caminho antigo acabar.
  • Em uploads por streaming, chame a URL final diretamente em vez de depender do redirecionamento.

Como enviar um 308

Express (Node.js)
// v1 is retired; clients keep POSTing, so the method must survive
app.use('/api/v1', (req, res) => {
  // req.url is the path after the mount point, query string included
  res.redirect(308, '/api/v2' + req.url);
});
Next.js App Router (route handler)
// next.config.js: permanent: true sends 308
module.exports = {
  async redirects() {
    return [
      { source: '/api/v1/:path*', destination: '/api/v2/:path*', permanent: true }
    ];
  }
};

// In a route handler: Response.redirect(new URL('/api/v2/upload', request.url), 308)
// In pages and Server Components: permanentRedirect('/new') from next/navigation
Go net/http
mux.HandleFunc("/api/v1/", func(w http.ResponseWriter, r *http.Request) {
	target := "/api/v2/" + strings.TrimPrefix(r.URL.Path, "/api/v1/")
	http.Redirect(w, r, target, http.StatusPermanentRedirect) // 308
})
Python FastAPI
from fastapi import FastAPI
from fastapi.responses import RedirectResponse

app = FastAPI()

@app.api_route("/api/v1/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
def v1_moved(path: str):
    return RedirectResponse(f"/api/v2/{path}", status_code=308)
Nginx
# rewrite ... permanent would send 301; return gives a 308
location ~ ^/api/v1/(.*)$ {
  return 308 /api/v2/$1$is_args$args;
}

Costuma ser confundido com

308 vs 301
Mesma permanência e mesmo tratamento no SEO; o 301 deixa o cliente reenviar POST como GET, o 308 não.
308 vs 307
O 307 também mantém o método, mas é temporário: não vai para o cache por padrão e não é sinal de URL canônica para buscadores.

Perguntas frequentes

Qual a diferença entre 301 e 308?
Os dois dizem que o recurso mudou de vez e os dois ficam no cache do navegador. O 301 deixa o cliente trocar POST por GET no pedido seguinte, e o navegador troca; o 308 exige o mesmo método e corpo.
O redirecionamento 308 é bom para SEO?
Sim. A documentação do Google coloca o 308 como equivalente ao 301: um sinal forte de que o destino do redirecionamento deve ser a URL canônica.
Por que o Next.js responde 308 e não 301?
O Next.js usa 308 nos redirects com permanent: true, no permanentRedirect() e no trailingSlash para que pedidos que não são GET mantenham o método. Se você precisa de um 301 literal, use statusCode: 301 no lugar de permanent no redirect do next.config.
Todos os navegadores aceitam o status 308?
Todos os navegadores atuais sim. O Internet Explorer 11 só seguia o 308 no Windows 10; no Windows 7 e 8.1 mostrava uma página de erro.

Revisado em por Arielton Oberek.