PHP

Dominando Headers HTTP em PHP: Redirecionamentos e Respostas em Projetos Reais

8 min de leitura

Dominando Headers HTTP em PHP: Redirecionamentos e Respostas em Projetos Reais

Headers HTTP em PHP: Redirecionamentos e Respostas O Que São Headers HTTP e Por Que Importam 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 é a ferramenta principal, mas exige cuidado: deve ser chamada antes de qualquer saída (echo, espaço em branco ou HTML). 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. Redirecionamentos HTTP com Redirecionamento Simples (Status 302) O redirecionamento 302 (Found) é temporário. Use quando o destino pode mudar: Sempre chame após para evitar que código abaixo execute. O navegador segue automaticamente a URL. Redirecionamento Permanente (Status 301)

<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 &quot;Headers already sent&quot; — 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">&lt;?php

// Redireciona para outra página

header(&quot;Location: https://exemplo.com/nova-pagina&quot;);

exit; // Importante: encerra o script

?&gt;</code></pre>

<p>Sempre chame <code>exit()</code> após <code>header(&quot;Location:&quot;)</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">&lt;?php

header(&quot;HTTP/1.1 301 Moved Permanently&quot;);

header(&quot;Location: https://exemplo.com/pagina-antiga-agora-aqui&quot;);

exit;

?&gt;</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">&lt;?php

session_start();

// Verifica autenticação

if (!isset($_SESSION[&#039;usuario_id&#039;])) {

header(&quot;Location: /login.php&quot;);

exit;

}

// Processamento normal

echo &quot;Bem-vindo, &quot; . htmlspecialchars($_SESSION[&#039;usuario_id&#039;]);

?&gt;</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">&lt;?php

// Retornando JSON

header(&quot;Content-Type: application/json; charset=utf-8&quot;);

$dados = [&#039;status&#039; =&gt; &#039;sucesso&#039;, &#039;mensagem&#039; =&gt; &#039;Operação concluída&#039;];

echo json_encode($dados);

exit;

?&gt;</code></pre>

<pre><code class="language-php">&lt;?php

// Forçando download de arquivo

header(&quot;Content-Type: application/pdf&quot;);

header(&quot;Content-Disposition: attachment; filename=&#039;documento.pdf&#039;&quot;);

readfile(&#039;/caminho/local/documento.pdf&#039;);

exit;

?&gt;</code></pre>

<h4>Cache e Headers de Controle</h4>

<p>Controle como navegadores e proxies armazenam sua resposta:</p>

<pre><code class="language-php">&lt;?php

// Desabilitar cache completamente

header(&quot;Cache-Control: no-cache, no-store, must-revalidate&quot;);

header(&quot;Pragma: no-cache&quot;);

header(&quot;Expires: 0&quot;);

// Para conteúdo estático (imagens, CSS)

header(&quot;Cache-Control: public, max-age=86400&quot;); // 1 dia

header(&quot;Expires: &quot; . gmdate(&quot;D, d M Y H:i:s&quot;, time() + 86400) . &quot; GMT&quot;);

?&gt;</code></pre>

<h4>Headers de Segurança</h4>

<p>Implemente proteções essenciais:</p>

<pre><code class="language-php">&lt;?php

// Previne clickjacking

header(&quot;X-Frame-Options: SAMEORIGIN&quot;);

// Previne MIME sniffing

header(&quot;X-Content-Type-Options: nosniff&quot;);

// Ativa proteção XSS no navegador

header(&quot;X-XSS-Protection: 1; mode=block&quot;);

// CORS - controla requisições cross-origin

header(&quot;Access-Control-Allow-Origin: https://dominio-confiavel.com&quot;);

header(&quot;Access-Control-Allow-Methods: GET, POST, OPTIONS&quot;);

header(&quot;Access-Control-Allow-Headers: Content-Type&quot;);

?&gt;</code></pre>

<h3>Códigos de Status HTTP</h3>

<h4>Respostas de Sucesso (2xx)</h4>

<pre><code class="language-php">&lt;?php

// 200 OK - resposta bem-sucedida padrão (implícito)

header(&quot;HTTP/1.1 200 OK&quot;);

echo &quot;Operação realizada com sucesso&quot;;

// 201 Created - recurso criado

header(&quot;HTTP/1.1 201 Created&quot;);

header(&quot;Location: /recurso/123&quot;);

echo json_encode([&#039;id&#039; =&gt; 123]);

?&gt;</code></pre>

<h4>Erros do Cliente (4xx)</h4>

<pre><code class="language-php">&lt;?php

// 400 Bad Request

header(&quot;HTTP/1.1 400 Bad Request&quot;);

http_response_code(400);

echo json_encode([&#039;erro&#039; =&gt; &#039;Dados inválidos&#039;]);

exit;

// 403 Forbidden

if (!$usuario_autorizado) {

header(&quot;HTTP/1.1 403 Forbidden&quot;);

http_response_code(403);

echo &quot;Acesso negado&quot;;

exit;

}

// 404 Not Found

header(&quot;HTTP/1.1 404 Not Found&quot;);

http_response_code(404);

echo &quot;Página não encontrada&quot;;

exit;

?&gt;</code></pre>

<h4>Erros do Servidor (5xx)</h4>

<pre><code class="language-php">&lt;?php

// 500 Internal Server Error

try {

// Processamento perigoso

$resultado = operacao_critica();

} catch (Exception $e) {

header(&quot;HTTP/1.1 500 Internal Server Error&quot;);

http_response_code(500);

echo json_encode([&#039;erro&#039; =&gt; &#039;Erro interno do servidor&#039;]);

error_log($e-&gt;getMessage());

exit;

}

?&gt;</code></pre>

<h3>Boas Práticas e Armadilhas</h3>

<p>Evite espaços em branco antes de <code>&lt;?php</code>:</p>

<pre><code class="language-php">&lt;?php // Correto - sem espaço antes da tag

header(&quot;Location: /home&quot;);

exit;

?&gt;</code></pre>

<pre><code class="language-php">&lt;?php

// Errado - espaço/quebra de linha depois de ?&gt;

?&gt;

header(&quot;Location: /home&quot;);</code></pre>

<p>Use <code>http_response_code()</code> para compatibilidade moderna:</p>

<pre><code class="language-php">&lt;?php

http_response_code(301);

header(&quot;Location: /nova-url&quot;);

exit;

// Ou verifique headers já enviados

if (!headers_sent()) {

header(&quot;Content-Type: application/json&quot;);

} else {

// Fallback com JavaScript

echo &quot;&lt;script&gt;window.location=&#039;/nova-url&#039;;&lt;/script&gt;&quot;;

}

?&gt;</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>

Comentários

Mais em PHP

Guia Completo de Orientação a Objetos em PHP: Classes, Objetos e Propriedades
Guia Completo de Orientação a Objetos em PHP: Classes, Objetos e Propriedades

Introdução: O Que é Orientação a Objetos em PHP Orientação a Objetos (OO) é u...

Camada Controller: Recebendo Requisições e Orquestrando Respostas na Prática
Camada Controller: Recebendo Requisições e Orquestrando Respostas na Prática

O Papel do Controller na Arquitetura MVC O controller é o intermediário funda...

Construindo uma API REST Completa com Laravel na Prática
Construindo uma API REST Completa com Laravel na Prática

Fundações: Preparando o Ambiente Antes de construir sua API REST em Laravel,...