Foundation · 45 MINUTES · VERSION 1
Read HTTP requests and choose response statuses
Inspect method, headers, JSON, and status. Run a local validation preview and test malformed input, missing paths, and unsupported methods.
Reviewed 23 Oct 2026Your setup may differ. Windows, Ubuntu, and optional tool bundles →
What you will learn
- Find a request method, path, header, and body.
- Choose a useful success or error response status.
- Run a local HTTP experiment and inspect its actual headers and JSON.
Theory: the parts of a request
HTTP is the protocol that lets a client exchange messages with a server. A request has a method such as GET or POST, a target such as /tasks, headers, and sometimes a body. A header describes the message; a JSON body carries data. Content-Type: application/json says how the body is encoded. It does not prove the data is valid.
A response has a status, headers, and usually a body. The status tells the client how the request went. The body can explain details. Choose both consistently; an error message inside a 200 response can cause clients and monitoring to treat failure as success.
| Status | Use in a task application |
|---|---|
| 200 OK | A successful read or validation preview. |
| 201 Created | A new resource was actually created; provide its location when appropriate. |
| 204 No Content | Success with no response body. Do not attach JSON. |
| 400 Bad Request | The request is malformed, such as broken JSON in this lab. |
| 401 Unauthorized | Valid authentication is required; the response includes the appropriate authentication challenge. |
| 403 Forbidden | Access is refused; logging in again may not help. |
| 404 Not Found | The requested resource or route is not available. |
| 405 Method Not Allowed | The path exists but the method is unsupported; include Allow. |
| 422 Unprocessable Content | The content is understood, but values fail the endpoint's rules. |
| 500 Internal Server Error | The server failed unexpectedly. Keep sensitive internals out of public errors. |
These are common meanings, not a complete API design policy. A Laravel HTML form may redirect back with validation errors, while a JSON API normally returns an error response. Request headers and middleware affect that behavior. Do not disable CSRF protection to make a real browser form work.
Worked example: a local response lab
Required: PHP 8.4 or a compatible newer runtime. No database, Laravel project, AI service, or Python runtime is needed by the learner. Save this original example as http_responses.php in a separate practice folder. It uses dummy tasks and validates a proposed title. It does not store or create a task, so a valid POST returns a 200 preview rather than claiming 201 Created.
<?php
declare(strict_types=1);
// Local learning router. No database, login, or persistent task creation.
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
$code = 200;
$headers = [];
if ($path !== '/tasks') {
$code = 404;
$body = ['error' => 'Route not found.'];
} elseif (! in_array($method, ['GET', 'POST'], true)) {
$code = 405;
$headers['Allow'] = 'GET, POST';
$body = ['error' => 'Use GET or POST.'];
} elseif ($method === 'GET') {
$body = ['tasks' => [['id' => 1, 'title' => 'Read one lesson']]];
} else {
try {
$input = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
if (! is_array($input) || ! is_string($input['title'] ?? null) || trim($input['title']) === '' || strlen($input['title']) > 100) {
$code = 422;
$body = ['error' => 'Title must contain 1 to 100 bytes of text.'];
} else {
$body = ['title' => trim($input['title']), 'saved' => false];
}
} catch (JsonException) {
$code = 400;
$body = ['error' => 'Invalid JSON.'];
}
}
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
foreach ($headers as $name => $value) {
header($name.': '.$value);
}
echo json_encode($body, JSON_THROW_ON_ERROR);
Start a temporary server from that practice folder:
php -S 127.0.0.1:8010 http_responses.php
The command works in Windows PowerShell/Command Prompt and Ubuntu Bash when PHP is on PATH. The port 8010 is an example; choose another unused port if needed. For this site's tracked file, run php -S 127.0.0.1:8010 content/labs/http_responses.php from the repository root. Do not replace the site's existing port 8003 server. Keep this practice server local. PHP's built-in development server is not a production deployment option. Stop only this practice terminal with Ctrl+C when finished.
Open http://127.0.0.1:8010/tasks in a browser. In developer tools, open Network and reload the page. Select the document request. Expect method GET, response status 200, a JSON Content-Type, and this body:
{"tasks":[{"id":1,"title":"Read one lesson"}]}
The browser may send another request for an icon; inspect /tasks, not the icon request. Opening /missing returns status 404 and {"error":"Route not found."}.
Guided practice: send a JSON body
Use a second terminal while the practice server stays running. For Windows PowerShell:
$result = Invoke-WebRequest -Uri http://127.0.0.1:8010/tasks -Method POST -ContentType 'application/json' -Body '{"title":"Write one test"}' -UseBasicParsing
$result.StatusCode
$result.Content
Expect 200 and {"title":"Write one test","saved":false}. For Ubuntu Bash, use curl:
curl -i -X POST http://127.0.0.1:8010/tasks -H 'Content-Type: application/json' --data '{"title":"Write one test"}'
Expect a 200 status line, the JSON Content-Type header, and the same body. Command Prompt has different quoting rules; use the labelled PowerShell command in PowerShell rather than pasting Bash syntax into it. Windows curl can be an alias in some shells, so confirm the tool you use.
Now try these inputs with your chosen client. PowerShell versions may throw on non-success statuses; use Network tools or inspect the exception's response status rather than treating that client behavior as a crashed server.
| Change | Expected result |
|---|---|
POST body {"title":" "} |
422; title fails the rule. |
POST body { |
400; JSON cannot be decoded. |
POST body {"title":7} |
422; title is not a string. |
DELETE /tasks |
405 with Allow: GET, POST. |
GET /tasks?status=done |
200; this lab ignores query filters. |
This example limits a title using bytes, not user-perceived characters. UTF-8 text can use several bytes per character. Later use a deliberate Unicode-aware application rule and test it. A header claiming JSON is not a substitute for decoding and validating the actual body.
Independent exercise
Add GET /health returning status 200 with {"ok":true}. For another method on /health, return 405 with Allow: GET. Keep unknown paths at 404. Verify /health, POST /health, and /missing. Do not add a public endpoint that runs submitted PHP code.
Write a short report of method, path, status, one relevant header, and body for three requests. State clearly that the POST task example previews valid input and does not persist a task.
Common mistakes
- Reading only the body: inspect the status and headers too.
- Reporting 201 without creating anything: use the status that matches the real result.
- Returning a body with 204: choose either a body-bearing success response or a true no-content response.
- Confusing malformed JSON with a missing title: this lab distinguishes 400 from 422.
- Running this practice router on a public interface: bind to 127.0.0.1 and use dummy data.
Self-check — not graded
- Which header describes a JSON body?
- How do 404 and 405 differ?
- Why does a valid preview return 200 rather than 201?
Interview practice
“A client gets a 422 response. What do you check?” Inspect the method/path, content type, decoded body, field types, validation rules, and response details. Reproduce with dummy input. Do not expose real customer data or stack traces in a bug report.
English practice and glossary
- Method: the requested kind of operation, such as GET.
- Header: message metadata, such as Content-Type.
- Body: the message's content.
- Status: the response's result code.
- Validation: checking whether input follows rules.
- Persist: store data beyond this request.
Write: “I sent __ to __. I expected __. The actual status was __ because __.” Read the report aloud and point to the evidence in your client.
Recap and next step
Read the whole exchange: method, target, headers, body, and status. Use responses that match actual behavior. Next, learn to save and review a small Git change. Official references and review dates are listed below.
Reveal exercise hints and self-check answers
Content-Type: application/jsondescribes JSON content.- 404 means the target is unavailable. 405 means that target does not support the requested method and gives allowed methods in
Allow. - The endpoint only validates and previews input. It does not create a resource.
Exercise outline: handle /health before the unknown-path branch. Check its method explicitly and set an Allow header for unsupported methods. Keep the original /tasks branches unchanged. Self-review your report for correct status/header/body evidence and an honest statement about persistence.