http clients and apis
HTTP Fundamentals
Every HTTP exchange has a request and a response. The client sends a method, URL, headers, and sometimes a body. The server replies with a status code, headers, and usually a body.
Request line
The request line tells the server what the client wants to do and where.
GET /api/products/42 HTTP/1.1
In a PHP app, the method and path often arrive through $_SERVER.
<?php
declare(strict_types=1);
$method = 'GET';
$path = '/api/products/42';
echo $method . ' ' . $path . PHP_EOL;
// Prints:
// GET /api/products/42
In a real request, the path may include a query string such as /api/products?search=keyboard&page=2. The path identifies the resource; the query string usually carries filtering, sorting, pagination, or search values.
Methods have meaning
HTTP methods describe the kind of action the client is asking for.
GET reads a resource. It should not create orders, send emails, delete records, or do other state-changing work.
POST usually creates something or submits a command.
PUT commonly replaces a resource.
PATCH commonly updates part of a resource.
DELETE deletes a resource.
These are conventions, but they matter. They affect caching, retries, API design, browser behaviour, and how other developers understand the system.
<?php
declare(strict_types=1);
function methodPurpose(string $method): string
{
return match ($method) {
'GET' => 'read',
'POST' => 'create or submit',
'PUT' => 'replace',
'PATCH' => 'partial update',
'DELETE' => 'delete',
default => 'unknown',
};
}
echo methodPurpose('PATCH') . PHP_EOL;
// Prints:
// partial update
Headers describe metadata
Headers carry metadata about the request or response. Common examples:
Content-Type: what format the body usesAccept: what format the client wants backAuthorization: credentials for the requestUser-Agent: client informationCache-Control: caching instructions
<?php
declare(strict_types=1);
$headers = [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
];
echo $headers['Content-Type'] . PHP_EOL;
// Prints:
// application/json
Header names are case-insensitive, but it is still worth being consistent in your code and documentation.
Bodies carry data
Many POST, PUT, and PATCH requests include a body. For JSON APIs, the body is usually JSON:
{
"name": "Keyboard",
"price": 99.99
}
PHP form submissions commonly populate $_POST. Raw JSON bodies are usually read from php://input and decoded with json_decode().
Responses have status codes
Status codes tell the client how the request went.
<?php
declare(strict_types=1);
function statusMeaning(int $status): string
{
return match (true) {
$status >= 200 && $status < 300 => 'success',
$status >= 300 && $status < 400 => 'redirect',
$status >= 400 && $status < 500 => 'client error',
$status >= 500 && $status < 600 => 'server error',
default => 'unknown',
};
}
echo statusMeaning(404) . PHP_EOL;
// Prints:
// client error
Common API statuses include:
200 OK: successful response201 Created: a resource was created204 No Content: success with no response body400 Bad Request: malformed or invalid request401 Unauthorized: authentication is missing or invalid403 Forbidden: authenticated but not allowed404 Not Found: resource or route not found409 Conflict: request conflicts with current state422 Unprocessable Content: validation failed429 Too Many Requests: rate limit hit500 Internal Server Error: unexpected server failure
HTTP is stateless
HTTP does not remember previous requests by itself. State comes from cookies, sessions, tokens, databases, caches, and application code.
This is why APIs often send an Authorization header on every request, and browser apps send cookies on every request.
What to check in a project
Check that read actions use GET and state-changing actions do not.
Check that request bodies match the declared Content-Type.
Check that API responses use status codes that match the outcome.
Check that errors return useful, safe messages without leaking secrets or stack traces.
Check logs for enough request information to debug failures: method, path, status, request ID, and timing.
What you should be able to do
After this lesson, you should be able to describe the parts of an HTTP request and response, choose sensible methods and status codes, explain what headers are for, and recognise why statelessness matters in PHP applications and APIs.
Practice
Task: Describe HTTP Exchanges
Write a small PHP script that describes a few HTTP request/response examples.
Requirements
- Use
declare(strict_types=1);. - Create a function that accepts method, path, and status code.
- Return a short sentence describing the exchange.
- Include a successful
GET. - Include a created
POST. - Include a client error such as
404. - Print the results.
Check Your Work
Run the script and confirm the output distinguishes methods and status-code groups.
Show solution
This solution classifies the response status and includes the method and path so the full exchange is visible.
<?php
declare(strict_types=1);
function statusGroup(int $status): string
{
return match (true) {
$status >= 200 && $status < 300 => 'success',
$status >= 300 && $status < 400 => 'redirect',
$status >= 400 && $status < 500 => 'client error',
$status >= 500 && $status < 600 => 'server error',
default => 'unknown',
};
}
function describeExchange(string $method, string $path, int $status): string
{
return $method . ' ' . $path . ' returned ' . $status . ' (' . statusGroup($status) . ')';
}
echo describeExchange('GET', '/api/products/42', 200) . PHP_EOL;
echo describeExchange('POST', '/api/products', 201) . PHP_EOL;
echo describeExchange('GET', '/api/missing', 404) . PHP_EOL;
// Prints:
// GET /api/products/42 returned 200 (success)
// POST /api/products returned 201 (success)
// GET /api/missing returned 404 (client error)
Why This Works
The examples show a read request, a create request, and a missing resource. That gives enough variety to practise method, path, and status-code meaning together.