diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-11-24 06:20:46 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-11-24 06:20:46 +0900 |
| commit | 75bcdb2bb75a12366aaee2fab82adc8b291ccb13 (patch) | |
| tree | 07a6f70e2b320dc96fd3d820ed6f467913518294 | |
| parent | de96eead05897bb40707efa0846b4088e42acebe (diff) | |
| download | nil.ninja-75bcdb2bb75a12366aaee2fab82adc8b291ccb13.tar.gz nil.ninja-75bcdb2bb75a12366aaee2fab82adc8b291ccb13.tar.zst nil.ninja-75bcdb2bb75a12366aaee2fab82adc8b291ccb13.zip | |
phpcon-kagawa-2025: Fix socket reading
| -rw-r--r-- | vhosts/t/phpcon-kagawa-2025/src/Http/Server.php | 64 | ||||
| -rw-r--r-- | vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php | 2 |
2 files changed, 63 insertions, 3 deletions
diff --git a/vhosts/t/phpcon-kagawa-2025/src/Http/Server.php b/vhosts/t/phpcon-kagawa-2025/src/Http/Server.php index cf13dcf..050f2c8 100644 --- a/vhosts/t/phpcon-kagawa-2025/src/Http/Server.php +++ b/vhosts/t/phpcon-kagawa-2025/src/Http/Server.php @@ -46,9 +46,11 @@ final readonly class Server implements ResponseFactoryInterface, StreamFactoryIn continue; } - $rawRequest = socket_read($sock, 8192); + echo 'Reading request...'; + $rawRequest = $this->readRequest($sock); + echo "done\n"; - if ($rawRequest) { + if ($rawRequest !== '') { $request = $this->parseRequest($rawRequest); echo 'Request: ' . $request->getMethod() . ' ' . $request->getRequestTarget() . "\n"; @@ -90,6 +92,64 @@ final readonly class Server implements ResponseFactoryInterface, StreamFactoryIn throw new RuntimeException('Not implemented'); } + /** + * @param \Socket $sock + */ + private function readRequest($sock): string + { + // Set socket timeout (5 seconds) + socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, [ + 'sec' => 5, + 'usec' => 0, + ]); + + $rawRequest = ''; + $headersComplete = false; + $contentLength = 0; + $headerEndPos = 0; + + // Read headers first + for (; ;) { + $chunk = ''; + $bytes = socket_recv($sock, $chunk, 8192, 0); + if ($bytes === false || $bytes === 0 || $chunk === null) { + break; + } + $rawRequest .= $chunk; + + // Check if headers are complete + $headerEndPos = strpos($rawRequest, "\r\n\r\n"); + if ($headerEndPos !== false) { + $headersComplete = true; + $headerEndPos += 4; // Include \r\n\r\n + + // Parse Content-Length from headers + $headerSection = substr($rawRequest, 0, $headerEndPos); + if (preg_match('/^Content-Length:\s*(\d+)/mi', $headerSection, $matches)) { + $contentLength = (int) $matches[1]; + } + break; + } + } + + // Read body based on Content-Length + if ($headersComplete && $contentLength > 0) { + $bodyReceived = strlen($rawRequest) - $headerEndPos; + while ($bodyReceived < $contentLength) { + $chunk = ''; + $remaining = $contentLength - $bodyReceived; + $bytes = socket_recv($sock, $chunk, min($remaining, 8192), 0); + if ($bytes === false || $bytes === 0 || $chunk === null) { + break; + } + $rawRequest .= $chunk; + $bodyReceived += $bytes; + } + } + + return $rawRequest; + } + private function parseRequest(string $rawRequest): ServerRequest { $lines = explode("\r\n", $rawRequest); diff --git a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php index 893a2ba..ee5a730 100644 --- a/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php +++ b/vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php @@ -43,7 +43,7 @@ final readonly class PostHandler implements RequestHandlerInterface <body> <main> <h1>本州四国連絡橋クイズ</h1> - <p>四国の各県と橋でつながっている中国地方の県を選んでください。</p> + <p>四国の各県と橋でつながっている本州の県を選んでください。</p> <form method="POST" action="/phpcon-kagawa-2025/post/"> <div> <label>愛媛とつながっているのは?</label> |
