HTTP Headers

Controlling HTTP responses with PHP's header functions

The $_SERVER Superglobal

PHP puts all request metadata into the $_SERVER superglobal array. This includes the HTTP method, URL path, query string, and all request headers:

Key Contains
REQUEST_METHOD GET, POST, PUT, DELETE, etc.
REQUEST_URI Full request path with query string
QUERY_STRING Just the query string portion
HTTP_HOST Requested hostname
HTTP_USER_AGENT Browser identification string
HTTP_ACCEPT Content types client accepts
CONTENT_TYPE Content-Type of request body
REMOTE_ADDR Client IP address

Setting Response Headers

PHP's header() function sets HTTP response headers. You can also set the status code with http_response_code():

Headers Must Come First

The header() function must be called before any output. PHP sends HTTP headers with the first byte of output, so even a single space or newline before <?php will cause an error.

// WRONG - whitespace before PHP tag

Content Negotiation

A single PHP endpoint can return different formats based on what the client requests via the Accept header:

'Alice', 'role' => 'admin']; $accept = $_SERVER['HTTP_ACCEPT'] ?? ''; if (strpos($accept, 'application/json') !== false) { header('Content-Type: application/json'); echo json_encode($data); } else { header('Content-Type: text/html'); echo "

{$data['name']}

"; echo "

Role: {$data['role']}

"; } ?>

Test it with curl:

# Request HTML (default) curl http://localhost:8000/content-negotiation.php # Request JSON curl -H "Accept: application/json" http://localhost:8000/content-negotiation.php

Reading Raw Request Body

For JSON APIs, form data is not available in $_POST. PHP's $_POST only works for application/x-www-form-urlencoded and multipart/form-data. For JSON bodies, you must read the raw input stream:

'Invalid JSON']); exit; } // Now $data is a PHP associative array echo "Received: " . $data['name']; ?>

Testing with curl

Use curl to send different types of requests and inspect headers:

# GET request (see response headers with -v) curl -v http://localhost:8000/content-negotiation.php # Request JSON via Accept header curl -H "Accept: application/json" http://localhost:8000/content-negotiation.php # POST JSON data curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"Alice","email":"alice@example.com"}' \ http://localhost:8000/raw-body.php

Summary

  • $_SERVER contains all request metadata — HTTP headers become HTTP_* keys
  • header() sets response headers and must be called before any output
  • http_response_code() sets the HTTP status code
  • Content negotiation lets a single endpoint return JSON or HTML based on the Accept header
  • JSON request bodies require reading php://input since $_POST only handles form-encoded data