summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-11-24 06:20:46 +0900
committernsfisis <nsfisis@gmail.com>2025-11-24 06:20:46 +0900
commit75bcdb2bb75a12366aaee2fab82adc8b291ccb13 (patch)
tree07a6f70e2b320dc96fd3d820ed6f467913518294
parentde96eead05897bb40707efa0846b4088e42acebe (diff)
downloadnil.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.php64
-rw-r--r--vhosts/t/phpcon-kagawa-2025/src/PhpConKagawa2025/PostHandler.php2
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>