Skip to content

Commit 154d5d1

Browse files
authored
Merge pull request #126 from clue-labs/head-requests
Improve documentation for routing HTTP `HEAD` requests
2 parents d062062 + a160314 commit 154d5d1

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

docs/api/app.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ you can use this additional shortcut:
7070
$app->any('/user/{id}', $controller);
7171
```
7272

73+
Any registered `GET` routes will also match HTTP `HEAD` requests by default,
74+
unless a more explicit `HEAD` route can also be matched. Responses to HTTP `HEAD`
75+
requests can never have a response body, so X will automatically discard any
76+
HTTP response body in this case.
77+
7378
## Redirects
7479

7580
The `App` also offers a convenient helper method to redirect a matching route to

examples/index.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,31 @@
109109
$request->getMethod() . "\n"
110110
);
111111
});
112+
$app->get('/method/get', function (ServerRequestInterface $request) {
113+
return React\Http\Message\Response::plaintext(
114+
"GET\n"
115+
)->withHeader('X-Is-Head', $request->getMethod() === 'HEAD' ? 'true' : 'false');
116+
});
117+
$app->head('/method/head', function (ServerRequestInterface $request) {
118+
return new React\Http\Message\Response(
119+
React\Http\Message\Response::STATUS_OK,
120+
[
121+
'Content-Length' => 5,
122+
'Content-Type' => 'text/plain; charset=utf-8',
123+
'X-Is-Head' => 'true'
124+
]
125+
);
126+
});
127+
$app->get('/method/head', function (ServerRequestInterface $request) {
128+
return new React\Http\Message\Response(
129+
React\Http\Message\Response::STATUS_OK,
130+
[
131+
'Content-Type' => 'text/plain; charset=utf-8',
132+
'X-Is-Head' => 'false'
133+
],
134+
"HEAD\n"
135+
);
136+
});
112137

113138
$app->get('/etag/', function (ServerRequestInterface $request) {
114139
$etag = '"_"';

tests/acceptance.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ out=$(curl -v $base/method -X DELETE 2>&1); match "HTTP/.* 200" && match "DE
102102
out=$(curl -v $base/method -X OPTIONS 2>&1); match "HTTP/.* 200" && match "OPTIONS"
103103
out=$(curl -v $base -X OPTIONS --request-target "*" 2>&1); skipif "Server: nginx" && match "HTTP/.* 200" # skip nginx (400)
104104

105+
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$"
106+
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]"
107+
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$"
108+
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)
109+
105110
out=$(curl -v $base/etag/ 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 0[\r\n]" && match -iP "Etag: \"_\""
106111
out=$(curl -v $base/etag/ -H 'If-None-Match: "_"' 2>&1); match "HTTP/.* 304" && notmatch -i "Content-Length" && match -iP "Etag: \"_\""
107112
out=$(curl -v $base/etag/a 2>&1); match "HTTP/.* 200" && match -iP "Content-Length: 2[\r\n]" && match -iP "Etag: \"a\""

0 commit comments

Comments
 (0)