Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Http/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ public function start()
public function match(Request $request): ?Route
{
$url = \parse_url($request->getURI(), PHP_URL_PATH);

if ($url === null || $url === false) {
$url = '/'; // Default to root path for malformed URLs
}

$method = $request->getMethod();
$method = (self::REQUEST_METHOD_HEAD == $method) ? self::REQUEST_METHOD_GET : $method;

Expand Down
52 changes: 52 additions & 0 deletions tests/HttpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,58 @@ public function testCanMatchRoute(string $method, string $path, ?string $url = n
$this->assertEquals($expected, $route);
}

public function testMatchWithNullPath(): void
{
// Create a route for root path
$expected = Http::get('/');

// Test case where parse_url returns null (malformed URL)
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = '?param=1'; // This will cause parse_url to return null for PATH component

$matched = $this->http->match(new Request());
$this->assertEquals($expected, $matched);
}

public function testMatchWithEmptyPath(): void
{
// Create a route for root path
$expected = Http::get('/');

// Test case where URI has no path component
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = 'https://example.com'; // No path component

$matched = $this->http->match(new Request());
$this->assertEquals($expected, $matched);
}

public function testMatchWithMalformedURL(): void
{
// Create a route for root path
$expected = Http::get('/');

// Test case where parse_url returns false (severely malformed URL)
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = '#fragment'; // Malformed scheme

$matched = $this->http->match(new Request());
$this->assertEquals($expected, $matched);
}
Comment on lines +637 to +648
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify that this URI actually causes parse_url to return false.

The test intent is good, but the URI '#fragment' might not actually cause parse_url to return false. It would more likely return null for the path component since fragments are valid URL components.

Let me verify the behavior of parse_url with this URI:


🏁 Script executed:

#!/bin/bash
# Description: Test parse_url behavior with the fragment-only URI to verify it returns false vs null

php -r "
echo 'Testing parse_url behavior with fragment-only URI:' . PHP_EOL;
echo 'URI: #fragment' . PHP_EOL;
\$result = parse_url('#fragment', PHP_URL_PATH);
echo 'parse_url result: ';
var_dump(\$result);
echo 'Result === null: ' . ((\$result === null) ? 'true' : 'false') . PHP_EOL;
echo 'Result === false: ' . ((\$result === false) ? 'true' : 'false') . PHP_EOL;
echo PHP_EOL;

echo 'Testing with a truly malformed URL:' . PHP_EOL;
\$malformed = 'http://[invalid-ipv6';
echo 'URI: ' . \$malformed . PHP_EOL;
\$result2 = parse_url(\$malformed, PHP_URL_PATH);
echo 'parse_url result: ';
var_dump(\$result2);
echo 'Result === null: ' . ((\$result2 === null) ? 'true' : 'false') . PHP_EOL;
echo 'Result === false: ' . ((\$result2 === false) ? 'true' : 'false') . PHP_EOL;
"

Length of output: 1151


Use a URI that actually makes parse_url() return false
PHP’s parse_url('#fragment') does not return false (it returns null for the path component), so this test never hits the “false” branch. To cover a truly malformed URI, update the test in tests/HttpTest.php (lines 637–648) to something like:

$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI']    = 'http://[invalid-ipv6';
$matched = $this->http->match(new Request());
$this->assertEquals(Http::get('/'), $matched);

Alternatively, if you want to keep '#fragment', adjust the assertion to reflect that parse_url() returns null/empty path rather than false.

🤖 Prompt for AI Agents
In tests/HttpTest.php around lines 637 to 648, the test uses '#fragment' as the
REQUEST_URI, but parse_url('#fragment') does not return false, so the false
branch is never tested. To fix this, replace the REQUEST_URI value with a truly
malformed URI like 'http://[invalid-ipv6' that causes parse_url() to return
false, ensuring the test covers the intended case.


public function testMatchWithOnlyQueryString(): void
{
// Create a route for root path
$expected = Http::get('/');

// Test case where URI has only query string (no path)
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = '?param=value'; // Only query string, no path

$matched = $this->http->match(new Request());
$this->assertEquals($expected, $matched);
}

public function testNoMismatchRoute(): void
{
$requests = [
Expand Down