Skip to content

Commit

Permalink
Merge pull request #126 from clue-labs/head-requests
Browse files Browse the repository at this point in the history
Improve documentation for routing HTTP `HEAD` requests
  • Loading branch information
SimonFrings committed Mar 4, 2022
2 parents d062062 + a160314 commit 154d5d1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/api/app.md
Expand Up @@ -70,6 +70,11 @@ you can use this additional shortcut:
$app->any('/user/{id}', $controller);
```

Any registered `GET` routes will also match HTTP `HEAD` requests by default,
unless a more explicit `HEAD` route can also be matched. Responses to HTTP `HEAD`
requests can never have a response body, so X will automatically discard any
HTTP response body in this case.

## Redirects

The `App` also offers a convenient helper method to redirect a matching route to
Expand Down
25 changes: 25 additions & 0 deletions examples/index.php
Expand Up @@ -109,6 +109,31 @@
$request->getMethod() . "\n"
);
});
$app->get('/method/get', function (ServerRequestInterface $request) {
return React\Http\Message\Response::plaintext(
"GET\n"
)->withHeader('X-Is-Head', $request->getMethod() === 'HEAD' ? 'true' : 'false');
});
$app->head('/method/head', function (ServerRequestInterface $request) {
return new React\Http\Message\Response(
React\Http\Message\Response::STATUS_OK,
[
'Content-Length' => 5,
'Content-Type' => 'text/plain; charset=utf-8',
'X-Is-Head' => 'true'
]
);
});
$app->get('/method/head', function (ServerRequestInterface $request) {
return new React\Http\Message\Response(
React\Http\Message\Response::STATUS_OK,
[
'Content-Type' => 'text/plain; charset=utf-8',
'X-Is-Head' => 'false'
],
"HEAD\n"
);
});

$app->get('/etag/', function (ServerRequestInterface $request) {
$etag = '"_"';
Expand Down
5 changes: 5 additions & 0 deletions tests/acceptance.sh
Expand Up @@ -102,6 +102,11 @@ out=$(curl -v $base/method -X DELETE 2>&1); match "HTTP/.* 200" && match "DE
out=$(curl -v $base/method -X OPTIONS 2>&1); match "HTTP/.* 200" && match "OPTIONS"
out=$(curl -v $base -X OPTIONS --request-target "*" 2>&1); skipif "Server: nginx" && match "HTTP/.* 200" # skip nginx (400)

out=$(curl -v $base/method/get 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 4[\r\n]" && match -iP "Content-Type: text/plain; charset=utf-8[\r\n]" && match -iP "X-Is-Head: false[\r\n]" && match -P "GET$"
out=$(curl -v $base/method/get -I 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 4[\r\n]" && match -iP "Content-Type: text/plain; charset=utf-8[\r\n]" && match -iP "X-Is-Head: true[\r\n]"
out=$(curl -v $base/method/head 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 5[\r\n]" && match -iP "Content-Type: text/plain; charset=utf-8[\r\n]" && match -iP "X-Is-Head: false[\r\n]" && match -P "HEAD$"
out=$(curl -v $base/method/head -I 2>&1); skipif "Server: ReactPHP" && match "HTTP/.* 200" && match -iP "Content-Length: 5[\r\n]" && match -iP "Content-Type: text/plain; charset=utf-8[\r\n]" && match -iP "X-Is-Head: true[\r\n]" # skip built-in webserver (always includes Content-Length : 0)

out=$(curl -v $base/etag/ 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 0[\r\n]" && match -iP "Etag: \"_\""
out=$(curl -v $base/etag/ -H 'If-None-Match: "_"' 2>&1); match "HTTP/.* 304" && notmatch -i "Content-Length" && match -iP "Etag: \"_\""
out=$(curl -v $base/etag/a 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 2[\r\n]" && match -iP "Etag: \"a\""
Expand Down

0 comments on commit 154d5d1

Please sign in to comment.