Skip to content

Commit ba260b7

Browse files
ahmad-cit22crynobonetaylorotwell
authored
[11.x] Fix: Improve Request Port Extraction Handling in ServeCommand.php to Prevent Artisan Command Failures (#53538)
* Fix: Improve Request Port Extraction Handling in ServeCommand.php * update code formatting * Apply suggestions from code review * Move the Request Port extracting logic into a static method * add relevant unit tests * Fix style: correct docblock annotation * formatting * formatting --------- Co-authored-by: Mior Muhammad Zaki <[email protected]> Co-authored-by: Taylor Otwell <[email protected]>
1 parent 91e9de0 commit ba260b7

File tree

2 files changed

+88
-8
lines changed

2 files changed

+88
-8
lines changed

src/Illuminate/Foundation/Console/ServeCommand.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
use Illuminate\Support\Carbon;
77
use Illuminate\Support\Env;
88
use Illuminate\Support\InteractsWithTime;
9+
use InvalidArgumentException;
910
use Symfony\Component\Console\Attribute\AsCommand;
1011
use Symfony\Component\Console\Input\InputOption;
1112
use Symfony\Component\Process\Process;
12-
1313
use function Illuminate\Support\php_binary;
1414
use function Termwind\terminal;
1515

@@ -291,23 +291,23 @@ protected function flushOutputBuffer()
291291
}
292292

293293
if (str($line)->contains(' Accepted')) {
294-
$requestPort = $this->getRequestPortFromLine($line);
294+
$requestPort = static::getRequestPortFromLine($line);
295295

296296
$this->requestsPool[$requestPort] = [
297297
$this->getDateFromLine($line),
298298
$this->requestsPool[$requestPort][1] ?? false,
299299
microtime(true),
300300
];
301301
} elseif (str($line)->contains([' [200]: GET '])) {
302-
$requestPort = $this->getRequestPortFromLine($line);
302+
$requestPort = static::getRequestPortFromLine($line);
303303

304304
$this->requestsPool[$requestPort][1] = trim(explode('[200]: GET', $line)[1]);
305305
} elseif (str($line)->contains('URI:')) {
306-
$requestPort = $this->getRequestPortFromLine($line);
306+
$requestPort = static::getRequestPortFromLine($line);
307307

308308
$this->requestsPool[$requestPort][1] = trim(explode('URI: ', $line)[1]);
309309
} elseif (str($line)->contains(' Closing')) {
310-
$requestPort = $this->getRequestPortFromLine($line);
310+
$requestPort = static::getRequestPortFromLine($line);
311311

312312
if (empty($this->requestsPool[$requestPort])) {
313313
$this->requestsPool[$requestPort] = [
@@ -374,11 +374,15 @@ protected function getDateFromLine($line)
374374
* @param string $line
375375
* @return int
376376
*/
377-
protected function getRequestPortFromLine($line)
377+
public static function getRequestPortFromLine($line)
378378
{
379-
preg_match('/:(\d+)\s(?:(?:\w+$)|(?:\[.*))/', $line, $matches);
379+
preg_match('/(\[\w+\s\w+\s\d+\s[\d:]+\s\d{4}\]\s)?:(\d+)\s(?:(?:\w+$)|(?:\[.*))/', $line, $matches);
380+
381+
if (! isset($matches[2])) {
382+
throw new \InvalidArgumentException("Failed to extract the request port. Ensure the log line contains a valid port: {$line}");
383+
}
380384

381-
return (int) $matches[1];
385+
return (int) $matches[2];
382386
}
383387

384388
/**
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Foundation\Console;
4+
5+
use Illuminate\Foundation\Console\ServeCommand;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class ServeCommandLogParserTest extends TestCase
9+
{
10+
public function testExtractRequestPortWithValidLogLine()
11+
{
12+
$line = '[Mon Nov 19 10:30:45 2024] :8080 Info';
13+
14+
$this->assertEquals(8080, ServeCommand::getRequestPortFromLine($line));
15+
}
16+
17+
public function testExtractRequestPortWithValidLogLineAndExtraData()
18+
{
19+
$line = '[Mon Nov 19 10:30:45 2024] :3000 [Client Connected]';
20+
21+
$this->assertEquals(3000, ServeCommand::getRequestPortFromLine($line));
22+
}
23+
24+
public function testExtractRequestPortWithValidLogLineWithoutDate()
25+
{
26+
$line = ':5000 [Server Started]';
27+
28+
$this->assertEquals(5000, ServeCommand::getRequestPortFromLine($line));
29+
}
30+
31+
public function testExtractRequestPortWithMissingPort()
32+
{
33+
$line = '[Mon Nov 19 10:30:45 2024] Info';
34+
35+
$this->expectException(\InvalidArgumentException::class);
36+
$this->expectExceptionMessage('Failed to extract the request port. Ensure the log line contains a valid port: [Mon Nov 19 10:30:45 2024] Info');
37+
38+
ServeCommand::getRequestPortFromLine($line);
39+
}
40+
41+
public function testExtractRequestPortWithInvalidPortFormat()
42+
{
43+
$line = '[Mon Nov 19 10:30:45 2024] :abcd Info';
44+
45+
$this->expectException(\InvalidArgumentException::class);
46+
$this->expectExceptionMessage('Failed to extract the request port. Ensure the log line contains a valid port: [Mon Nov 19 10:30:45 2024] :abcd Info');
47+
48+
ServeCommand::getRequestPortFromLine($line);
49+
}
50+
51+
public function testExtractRequestPortWithEmptyLogLine()
52+
{
53+
$this->expectException(\InvalidArgumentException::class);
54+
$this->expectExceptionMessage('Failed to extract the request port. Ensure the log line contains a valid port: ');
55+
56+
ServeCommand::getRequestPortFromLine('');
57+
}
58+
59+
public function testExtractRequestPortWithWhitespaceOnlyLine()
60+
{
61+
$this->expectException(\InvalidArgumentException::class);
62+
$this->expectExceptionMessage('Failed to extract the request port. Ensure the log line contains a valid port: ');
63+
64+
ServeCommand::getRequestPortFromLine(' ');
65+
}
66+
67+
public function testExtractRequestPortWithRandomString()
68+
{
69+
$line = 'Random log entry without port';
70+
71+
$this->expectException(\InvalidArgumentException::class);
72+
$this->expectExceptionMessage('Failed to extract the request port. Ensure the log line contains a valid port: Random log entry without port');
73+
74+
ServeCommand::getRequestPortFromLine($line);
75+
}
76+
}

0 commit comments

Comments
 (0)