Headers HTTP são metadados enviados entre o servidor e o cliente, essenciais para controlar comportamento de cache, redirecionamentos, tipo de conteúdo e muito mais. Em PHP, a função header() é a principal ferramenta para manipular esses cabeçalhos diretamente no script.

Nesta aula, vamos explorar como usar header() para redirecionar o navegador, definir códigos de status HTTP e evitar erros comuns relacionados ao envio prematuro de saída. Compreender esses conceitos é fundamental para construir aplicações web robustas e seguras.

header()

A função header() envia um cabeçalho HTTP bruto ao cliente. Ela deve ser chamada antes de qualquer saída (echo, HTML, espaços em branco) para funcionar corretamente. Sua sintaxe básica é:

header(string $header, bool $replace = true, int $response_code = 0): void

O primeiro parâmetro é a string do cabeçalho, como "Content-Type: text/html". O segundo parâmetro ($replace) indica se o cabeçalho deve substituir um anterior do mesmo tipo (padrão true) ou adicionar outro (false). O terceiro permite forçar um código de resposta HTTP.

Exemplo de definição de tipo de conteúdo:

header('Content-Type: application/json');
echo json_encode(['status' => 'ok']);

Este cabeçalho informa ao cliente que a resposta é JSON, permitindo que o navegador ou API processe corretamente.

Redirecionamento (Location)

O redirecionamento é feito com o cabeçalho Location, que instrui o navegador a ir para outra URL. Deve ser acompanhado de um código de status 3xx (geralmente 302 para redirecionamento temporário ou 301 para permanente). Exemplo:

header('Location: https://example.com/novo-caminho');
exit;

É importante chamar exit (ou die) após o redirecionamento para garantir que o script pare de executar, evitando que código adicional seja enviado ao cliente. Caso contrário, o navegador pode ignorar o redirecionamento se houver saída posterior.

Para redirecionamentos permanentes, use o código 301:

header('Location: https://example.com/nova-pagina', true, 301);
exit;

O segundo parâmetro true (padrão) garante que qualquer cabeçalho Location anterior seja substituído.

Códigos HTTP

Códigos de status HTTP indicam o resultado de uma requisição. Os mais comuns em redirecionamentos são:

  • 301 Moved Permanently: recurso movido permanentemente; navegadores e mecanismos de busca atualizam o link.
  • 302 Found: redirecionamento temporário; o recurso original ainda é válido.
  • 303 See Other: usado após POST para redirecionar para uma página GET (evita reenvio de formulário).
  • 307 Temporary Redirect: similar ao 302, mas garante que o método HTTP não seja alterado.
  • 308 Permanent Redirect: similar ao 301, mas mantém o método HTTP.

Para definir o código de resposta, use http_response_code() ou o terceiro parâmetro de header(). Exemplo:

http_response_code(404);
echo 'Página não encontrada';

É boa prática usar códigos apropriados para cada situação, melhorando a semântica e o SEO.

Cuidados (output buffering)

Um erro comum é tentar enviar headers após já ter enviado saída (HTML, espaços, etc.). Isso gera o aviso "Cannot modify header information - headers already sent". Para evitar, use output buffering, que armazena a saída em buffer até que seja liberada.

Ative o buffer com ob_start() no início do script. Assim, mesmo que haja saída antes de header(), o PHP não envia nada imediatamente. Exemplo:

ob_start();
echo 'Algum texto'; // não é enviado ainda
header('Location: https://example.com');
ob_end_flush(); // envia tudo e libera o buffer
exit;

Funções úteis:

  • ob_start(): inicia o buffer de saída.
  • ob_end_flush(): envia o buffer e desliga o buffer.
  • ob_end_clean(): descarta o buffer sem enviar.
  • ob_get_contents(): obtém o conteúdo atual do buffer sem enviar.

Outra prática é verificar se headers já foram enviados com headers_sent():

if (!headers_sent()) {
    header('Location: https://example.com');
    exit;
} else {
    echo 'Não foi possível redirecionar';
}

Isso permite tomar ações alternativas em vez de gerar erro.

Boas práticas e observações finais

  • Sempre use exit após redirecionamentos para evitar execução desnecessária.
  • Prefira códigos HTTP semânticos (301 para permanente, 302 para temporário).
  • Evite enviar saída antes de headers; use output buffering se necessário.
  • Teste os cabeçalhos com ferramentas como o console do navegador (Network tab) ou curl -I.
  • Para redirecionamentos internos, use URLs relativas ou absolutas completas.

Referências

Exercícios

  1. Crie um script PHP que redirecione permanentemente (301) o usuário para https://www.example.com.

    ✓ Resposta:
    header('Location: https://www.example.com', true, 301);
    exit;
  2. Escreva um código que defina o cabeçalho Content-Type como text/plain e exiba a mensagem "Olá, mundo!" sem usar output buffering.

    ✓ Resposta:
    header('Content-Type: text/plain');
    echo 'Olá, mundo!';
  3. Implemente um script que verifique se o cabeçalho já foi enviado. Se não, redirecione para /login; caso contrário, exiba "Redirecionamento não possível".

    ✓ Resposta:
    if (!headers_sent()) {
        header('Location: /login');
        exit;
    } else {
        echo 'Redirecionamento não possível';
    }
  4. Corrija o código abaixo que gera erro "headers already sent":

    echo 'Antes';
    header('Location: /destino');
    exit;

    ✓ Resposta:Use output buffering:
    ob_start();
    echo 'Antes';
    header('Location: /destino');
    ob_end_flush();
    exit;
  5. Crie um script que redirecione para /sucesso com código 303 após um POST (simule usando $_SERVER['REQUEST_METHOD']).

    ✓ Resposta:
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        header('Location: /sucesso', true, 303);
        exit;
    }