Skip to content

Commit

Permalink
Merge pull request #6 from clue/urlencoded
Browse files Browse the repository at this point in the history
Automatically decode urlencoded (percent-encoded) attributes in URLs
  • Loading branch information
clue authored Feb 7, 2021
2 parents 49168d0 + 2cb0b67 commit 490c009
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
13 changes: 10 additions & 3 deletions examples/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@
});

$app->get('/users/{name}', function (Psr\Http\Message\ServerRequestInterface $request) {
$escape = function (string $str): string {
// replace invalid UTF-8 and control bytes with Unicode replacement character (�)
return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE | ENT_DISALLOWED, 'utf-8'));
};

return new React\Http\Message\Response(
200,
[],
"Hello " . $request->getAttribute('name') . "!\n"
[
'Content-Type' => 'text/plain'
],
"Hello " . $escape($request->getAttribute('name')) . "!\n"
);
});

$app->get('/uri', function (ServerRequestInterface $request) {
$app->get('/uri[/{path:.*}]', function (ServerRequestInterface $request) {
return new React\Http\Message\Response(
200,
[
Expand Down
2 changes: 1 addition & 1 deletion src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ private function handleRequest(ServerRequestInterface $request, Dispatcher $disp
$vars = $routeInfo[2];

foreach ($vars as $key => $value) {
$request = $request->withAttribute($key, $value);
$request = $request->withAttribute($key, rawurldecode($value));
}

return $handler($request);
Expand Down
23 changes: 22 additions & 1 deletion tests/acceptance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,26 @@ match() {
(echo ""; echo "Error in test $n: Unable to \"grep $@\" this output:"; echo "$out"; exit 1) || exit 1
}

skipif() {
echo "$out" | grep "$@" >/dev/null && echo -n S && return 1 || return 0
}

out=$(curl -v $base/ 2>&1); match "HTTP/.* 200"
out=$(curl -v $base/test 2>&1); match -i "Location: /"
out=$(curl -v $base/invalid 2>&1); match "HTTP/.* 404"
out=$(curl -v $base// 2>&1); match "HTTP/.* 404"
out=$(curl -v $base/ 2>&1 -X POST); match "HTTP/.* 405"

out=$(curl -v $base/uri 2>&1); match "HTTP/.* 200" && match "$base/uri"
out=$(curl -v $base/uri/ 2>&1); match "HTTP/.* 200" && match "$base/uri/"
out=$(curl -v $base/uri/foo 2>&1); match "HTTP/.* 200" && match "$base/uri/foo"
out=$(curl -v $base/uri/foo/bar 2>&1); match "HTTP/.* 200" && match "$base/uri/foo/bar"
out=$(curl -v $base/uri/foo//bar 2>&1); match "HTTP/.* 200" && match "$base/uri/foo//bar"
out=$(curl -v $base/uri/Wham! 2>&1); match "HTTP/.* 200" && match "$base/uri/Wham!"
out=$(curl -v $base/uri/Wham%21 2>&1); match "HTTP/.* 200" && match "$base/uri/Wham%21"
out=$(curl -v $base/uri/AC%2FDC 2>&1); skipif "HTTP/.* 404" && match "HTTP/.* 200" && match "$base/uri/AC%2FDC" # skip Apache (404 unless `AllowEncodedSlashes NoDecode`)
out=$(curl -v $base/uri/bin%00ary 2>&1); skipif "HTTP/.* 40[04]" && match "HTTP/.* 200" && match "$base/uri/bin%00ary" # skip nginx (400) and Apache (404)
out=$(curl -v $base/uri/AC/DC 2>&1); match "HTTP/.* 200" && match "$base/uri/AC/DC"
out=$(curl -v $base/uri? 2>&1); match "HTTP/.* 200" && match "$base/uri" # trailing "?" not reported for empty query string
out=$(curl -v $base/uri?query 2>&1); match "HTTP/.* 200" && match "$base/uri?query"
out=$(curl -v $base/uri?q=a 2>&1); match "HTTP/.* 200" && match "$base/uri?q=a"
Expand Down Expand Up @@ -43,7 +56,15 @@ out=$(curl -v $base/query?q=a%00b 2>&1); match "HTTP/.* 200" && m
out=$(curl -v $base/query?q=a\&q=b 2>&1); match "HTTP/.* 200" && match "{\"q\":\"b\"}"
out=$(curl -v $base/query?q%5B%5D=a\&q%5B%5D=b 2>&1); match "HTTP/.* 200" && match "{\"q\":[[]\"a\",\"b\"[]]}"

out=$(curl -v $base/users/foo 2>&1); match "HTTP/.* 200" && match "Hello foo!"
out=$(curl -v $base/users/foo 2>&1); match "HTTP/.* 200" && match "Hello foo!"
out=$(curl -v $base/users/w%C3%B6rld 2>&1); match "HTTP/.* 200" && match "Hello wörld!"
out=$(curl -v $base/users/w%F6rld 2>&1); match "HTTP/.* 200" && match "Hello w�rld!" # demo expects UTF-8 instead of ISO-8859-1
out=$(curl -v $base/users/a+b 2>&1); match "HTTP/.* 200" && match "Hello a+b!"
out=$(curl -v $base/users/Wham! 2>&1); match "HTTP/.* 200" && match "Hello Wham!!"
out=$(curl -v $base/users/Wham%21 2>&1); match "HTTP/.* 200" && match "Hello Wham!!"
out=$(curl -v $base/users/AC%2FDC 2>&1); skipif "HTTP/.* 404" && match "HTTP/.* 200" && match "Hello AC/DC!" # skip Apache (404 unless `AllowEncodedSlashes NoDecode`)
out=$(curl -v $base/users/bi%00n 2>&1); skipif "HTTP/.* 40[04]" && match "HTTP/.* 200" && match "Hello bi�n!" # skip nginx (400) and Apache (404)

out=$(curl -v $base/users 2>&1); match "HTTP/.* 404"
out=$(curl -v $base/users/ 2>&1); match "HTTP/.* 404"
out=$(curl -v $base/users/a/b 2>&1); match "HTTP/.* 404"
Expand Down

0 comments on commit 490c009

Please sign in to comment.