Nesta aula, vamos explorar o envio de cabeçalhos HTTP em PHP, uma funcionalidade essencial para controlar a comunicação entre o servidor e o cliente. A função header() permite modificar cabeçalhos da resposta, sendo amplamente utilizada para redirecionamentos, definição de tipo de conteúdo, cache e muito mais. Compreender seu funcionamento e as limitações relacionadas à saída de dados é fundamental para evitar erros e garantir a segurança das aplicações.

Veremos como redirecionar o navegador para outra URL usando o cabeçalho Location, os principais códigos de status HTTP e os cuidados necessários com o buffer de saída. Ao final, você será capaz de implementar redirecionamentos corretamente e diagnosticar problemas comuns.

header()

A função header() é usada para enviar um cabeçalho HTTP bruto ao cliente. Ela deve ser chamada antes de qualquer saída (echo, HTML, espaços em branco, etc.), pois os cabeçalhos são enviados antes do corpo da resposta. Sua sintaxe é:

header(string $header, bool $replace = true, int $response_code = 0): void
  • $header: string com o cabeçalho no formato "Nome: Valor".
  • $replace: se true (padrão), substitui um cabeçalho anterior com o mesmo nome; se false, adiciona múltiplos cabeçalhos (ex.: múltiplos Set-Cookie).
  • $response_code: força um código de status HTTP específico.

Exemplo de uso para definir o tipo de conteúdo como JSON:

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

Outro exemplo comum é forçar o download de um arquivo:

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="documento.pdf"');
readfile('caminho/para/documento.pdf');

Redirecionamento (Location)

O redirecionamento é realizado enviando o cabeçalho Location com a URL de destino. O PHP automaticamente envia um código de status 302 (Found) se nenhum outro código for especificado. Exemplo:

header('Location: https://www.exemplo.com');
exit; // sempre chamar exit após redirecionamento

É importante usar exit (ou die) após o redirecionamento para interromper a execução do script, evitando que o restante do código seja processado desnecessariamente. Para redirecionamentos permanentes (301), informe o código explicitamente:

header('Location: https://www.exemplo.com', true, 301);
exit;

Redirecionamentos podem ser condicionais, como após um login bem-sucedido:

if ($loginValido) {
    header('Location: /painel');
    exit;
} else {
    echo 'Credenciais inválidas.';
}

Códigos HTTP

Os códigos de status HTTP indicam o resultado da requisição. Os mais relevantes para redirecionamentos são:

  • 301 Moved Permanently: recurso movido permanentemente para nova URL. Usado para SEO, quando a URL antiga deve ser substituída.
  • 302 Found: redirecionamento temporário (padrão do PHP). Indica que o recurso está temporariamente em outra URL.
  • 303 See Other: usado após POST para redirecionar para uma página GET (padrão em PRG - Post/Redirect/Get).
  • 307 Temporary Redirect: similar ao 302, mas o método HTTP não pode ser alterado (ex.: se POST, permanece POST).
  • 308 Permanent Redirect: similar ao 301, mas preserva o método HTTP.

Outros códigos úteis para cabeçalhos:

  • 200 OK: sucesso (padrão).
  • 403 Forbidden: acesso negado.
  • 404 Not Found: recurso não encontrado.
  • 500 Internal Server Error: erro do servidor.

Exemplo de envio de código 404:

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

Cuidados (output buffering)

O maior cuidado ao usar header() é que ela deve ser chamada antes de qualquer saída para o navegador. Se houver qualquer saída (echo, print, HTML, espaços em branco, BOM do PHP), ocorrerá o erro "Cannot modify header information - headers already sent".

Para contornar isso, pode-se usar o buffer de saída (ob_start()). Esse recurso armazena toda a saída em um buffer interno, permitindo que os cabeçalhos sejam enviados posteriormente. Exemplo:

ob_start(); // inicia o buffer
?>
<!DOCTYPE html>
<html>
<head><title>Exemplo</title></head>
<body>
<?php
// Agora podemos enviar cabeçalhos mesmo após HTML
header('X-Custom: valor');
echo 'Conteúdo do corpo';
ob_end_flush(); // envia o buffer e desliga o buffer
?>

Outra boa prática é verificar se cabeçalhos já foram enviados com headers_sent():

if (!headers_sent()) {
    header('Location: /outra-pagina');
    exit;
} else {
    echo 'Não foi possível redirecionar, cabeçalhos já enviados.';
}

Além disso, evite espaços em branco antes da tag <?php e remova o BOM do arquivo (comum em editores como Notepad). O uso de frameworks geralmente gerencia o buffer automaticamente.

Boas práticas

  • Sempre use exit após redirecionamentos.
  • Prefira redirecionamentos absolutos ou relativos a partir da raiz (ex.: /pasta/pagina).
  • Para APIs, use códigos HTTP apropriados (ex.: 201 para criação, 400 para erros do cliente).
  • Evite enviar cabeçalhos após saída; se necessário, ative o output buffering.
  • Utilize http_response_code() para alterar o código de status de forma mais legível.

Referências

Exercícios

  1. Crie um script PHP que redirecione permanentemente (301) o usuário para "https://www.exemplo.com" e interrompa a execução.
  2. ✓ Resposta:
    <?php
    header('Location: https://www.exemplo.com', true, 301);
    exit;
    ?>
  3. Escreva um código que verifique se cabeçalhos já foram enviados; se não, redirecione para "/login" com código 302; caso contrário, exiba uma mensagem de erro.
  4. ✓ Resposta:
    <?php
    if (!headers_sent()) {
        header('Location: /login', true, 302);
        exit;
    } else {
        echo 'Erro: cabeçalhos já enviados. Não foi possível redirecionar.';
    }
    ?>
  5. Utilize output buffering para permitir que um cabeçalho personalizado seja enviado mesmo após algum HTML. Crie um script que inicia o buffer, imprime "Olá" e depois define um cabeçalho X-Custom.
  6. ✓ Resposta:
    <?php
    ob_start();
    echo 'Olá';
    header('X-Custom: meu-valor');
    ob_end_flush();
    ?>
  7. Implemente um redirecionamento para a página anterior (HTTP Referer) ou, se não existir, para a página inicial.
  8. ✓ Resposta:
    <?php
    $destino = $_SERVER['HTTP_REFERER'] ?? '/';
    header('Location: ' . $destino);
    exit;
    ?>
  9. Crie um script que defina o código de status como 404 e exiba uma mensagem personalizada, sem usar a função header() (use http_response_code).
  10. ✓ Resposta:
    <?php
    http_response_code(404);
    echo 'Página não encontrada';
    ?>