<h2>Headers HTTP em PHP: Redirecionamentos e Respostas</h2>
<h3>O Que São Headers HTTP e Por Que Importam</h3>
<p>Headers HTTP são informações enviadas entre cliente e servidor antes do corpo da resposta. Eles controlam cache, autenticação, tipo de conteúdo e comportamento do navegador. Em PHP, manipular headers corretamente é essencial para redirecionar usuários, definir cookies, controlar acesso e estruturar respostas adequadas. A função <code>header()</code> é a ferramenta principal, mas exige cuidado: deve ser chamada <strong>antes</strong> de qualquer saída (echo, espaço em branco ou HTML).</p>
<p>Erros ao trabalhar com headers causam "Headers already sent" — um dos problemas mais comuns em PHP. Entender o ciclo de vida da resposta HTTP evita frustrações e bugs difíceis de rastrear. Este artigo cobre desde o básico até padrões profissionais.</p>
<h3>Redirecionamentos HTTP com <code>header()</code></h3>
<h4>Redirecionamento Simples (Status 302)</h4>
<p>O redirecionamento 302 (Found) é temporário. Use quando o destino pode mudar:</p>
<pre><code class="language-php"><?php
// Redireciona para outra página
header("Location: https://exemplo.com/nova-pagina");
exit; // Importante: encerra o script
?></code></pre>
<p>Sempre chame <code>exit()</code> após <code>header("Location:")</code> para evitar que código abaixo execute. O navegador segue automaticamente a URL.</p>
<h4>Redirecionamento Permanente (Status 301)</h4>
<p>Use 301 (Moved Permanently) quando uma página foi movida definitivamente:</p>
<pre><code class="language-php"><?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: https://exemplo.com/pagina-antiga-agora-aqui");
exit;
?></code></pre>
<p>Navegadores e motores de busca armazenam 301 em cache. Use com moderação em URLs antigas para não quebrar SEO.</p>
<h4>Redirecionamento com Validação</h4>
<p>Padrão profissional: validar antes de redirecionar:</p>
<pre><code class="language-php"><?php
session_start();
// Verifica autenticação
if (!isset($_SESSION['usuario_id'])) {
header("Location: /login.php");
exit;
}
// Processamento normal
echo "Bem-vindo, " . htmlspecialchars($_SESSION['usuario_id']);
?></code></pre>
<h3>Controle de Respostas e Headers Personalizados</h3>
<h4>Definindo Tipo de Conteúdo</h4>
<p>O header <code>Content-Type</code> informa ao navegador como interpretar a resposta:</p>
<pre><code class="language-php"><?php
// Retornando JSON
header("Content-Type: application/json; charset=utf-8");
$dados = ['status' => 'sucesso', 'mensagem' => 'Operação concluída'];
echo json_encode($dados);
exit;
?></code></pre>
<pre><code class="language-php"><?php
// Forçando download de arquivo
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename='documento.pdf'");
readfile('/caminho/local/documento.pdf');
exit;
?></code></pre>
<h4>Cache e Headers de Controle</h4>
<p>Controle como navegadores e proxies armazenam sua resposta:</p>
<pre><code class="language-php"><?php
// Desabilitar cache completamente
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");
// Para conteúdo estático (imagens, CSS)
header("Cache-Control: public, max-age=86400"); // 1 dia
header("Expires: " . gmdate("D, d M Y H:i:s", time() + 86400) . " GMT");
?></code></pre>
<h4>Headers de Segurança</h4>
<p>Implemente proteções essenciais:</p>
<pre><code class="language-php"><?php
// Previne clickjacking
header("X-Frame-Options: SAMEORIGIN");
// Previne MIME sniffing
header("X-Content-Type-Options: nosniff");
// Ativa proteção XSS no navegador
header("X-XSS-Protection: 1; mode=block");
// CORS - controla requisições cross-origin
header("Access-Control-Allow-Origin: https://dominio-confiavel.com");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type");
?></code></pre>
<h3>Códigos de Status HTTP</h3>
<h4>Respostas de Sucesso (2xx)</h4>
<pre><code class="language-php"><?php
// 200 OK - resposta bem-sucedida padrão (implícito)
header("HTTP/1.1 200 OK");
echo "Operação realizada com sucesso";
// 201 Created - recurso criado
header("HTTP/1.1 201 Created");
header("Location: /recurso/123");
echo json_encode(['id' => 123]);
?></code></pre>
<h4>Erros do Cliente (4xx)</h4>
<pre><code class="language-php"><?php
// 400 Bad Request
header("HTTP/1.1 400 Bad Request");
http_response_code(400);
echo json_encode(['erro' => 'Dados inválidos']);
exit;
// 403 Forbidden
if (!$usuario_autorizado) {
header("HTTP/1.1 403 Forbidden");
http_response_code(403);
echo "Acesso negado";
exit;
}
// 404 Not Found
header("HTTP/1.1 404 Not Found");
http_response_code(404);
echo "Página não encontrada";
exit;
?></code></pre>
<h4>Erros do Servidor (5xx)</h4>
<pre><code class="language-php"><?php
// 500 Internal Server Error
try {
// Processamento perigoso
$resultado = operacao_critica();
} catch (Exception $e) {
header("HTTP/1.1 500 Internal Server Error");
http_response_code(500);
echo json_encode(['erro' => 'Erro interno do servidor']);
error_log($e->getMessage());
exit;
}
?></code></pre>
<h3>Boas Práticas e Armadilhas</h3>
<p>Evite espaços em branco antes de <code><?php</code>:</p>
<pre><code class="language-php"><?php // Correto - sem espaço antes da tag
header("Location: /home");
exit;
?></code></pre>
<pre><code class="language-php"><?php
// Errado - espaço/quebra de linha depois de ?>
?>
header("Location: /home");</code></pre>
<p>Use <code>http_response_code()</code> para compatibilidade moderna:</p>
<pre><code class="language-php"><?php
http_response_code(301);
header("Location: /nova-url");
exit;
// Ou verifique headers já enviados
if (!headers_sent()) {
header("Content-Type: application/json");
} else {
// Fallback com JavaScript
echo "<script>window.location='/nova-url';</script>";
}
?></code></pre>
<h2>Conclusão</h2>
<p>Dominar headers HTTP em PHP é fundamental para criar aplicações robustas e seguras. Os três pontos principais aprendidos são: <strong>(1)</strong> Headers devem ser enviados antes de qualquer saída, usando <code>header()</code> corretamente e sempre chamando <code>exit()</code> após redirecionamentos; <strong>(2)</strong> Escolher o código de status apropriado (301 vs 302, 200 vs 201, 4xx vs 5xx) comunica intenção clara ao cliente e aos motores de busca; <strong>(3)</strong> Implementar headers de segurança (X-Frame-Options, CORS, Cache-Control) é obrigação, não opcional, para proteger usuários e dados.</p>
<p>Pratique criando um sistema simples de autenticação com redirecionamentos condicionais e respostas JSON. O aprendizado consolidado só vem com experiência prática.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://www.php.net/manual/en/function.header.php" target="_blank" rel="noopener noreferrer">PHP Manual - Header Function</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" target="_blank" rel="noopener noreferrer">MDN Web Docs - HTTP Headers</a></li>
<li><a href="https://tools.ietf.org/html/rfc7231#section-6" target="_blank" rel="noopener noreferrer">HTTP Status Codes - RFC 7231</a></li>
<li><a href="https://owasp.org/www-project-secure-headers/" target="_blank" rel="noopener noreferrer">OWASP - HTTP Security Headers</a></li>
<li><a href="https://www.php.net/manual/en/function.http-response-code.php" target="_blank" rel="noopener noreferrer">PHP Manual - http_response_code</a></li>
</ul>