From 430758c3b77137977ef39a23714bfb63e616a009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EC=B0=BD=EC=9A=B1?= Date: Sun, 12 Jul 2026 00:49:52 +0900 Subject: [PATCH] feat(cloud): path-param router + dispatch --- cloud/src/Http/Router.php | 24 ++++++++++++++++++++++++ cloud/tests/RouterTest.php | 25 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 cloud/src/Http/Router.php create mode 100644 cloud/tests/RouterTest.php diff --git a/cloud/src/Http/Router.php b/cloud/src/Http/Router.php new file mode 100644 index 0000000..6065f5d --- /dev/null +++ b/cloud/src/Http/Router.php @@ -0,0 +1,24 @@ +[^/]+)', $path) . '$#'; + $this->routes[] = [strtoupper($method), $regex, $handler]; + } + + public function dispatch(Request $req): Response { + foreach ($this->routes as [$method, $regex, $handler]) { + if ($req->method() !== $method) continue; + if (preg_match($regex, $req->path(), $m)) { + $params = array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY); + return $handler($req, $params); + } + } + return Response::json(['error' => 'not_found'], 404); + } +} diff --git a/cloud/tests/RouterTest.php b/cloud/tests/RouterTest.php new file mode 100644 index 0000000..0b7c7b6 --- /dev/null +++ b/cloud/tests/RouterTest.php @@ -0,0 +1,25 @@ +add('GET', '/events/{id}', fn(Request $req, array $p) => Response::json(['id' => $p['id']])); + $res = $r->dispatch(new Request('GET', '/events/42', [], '', [], [])); + $this->assertSame(200, $res->status()); + $this->assertSame(['id' => '42'], json_decode($res->body(), true)); + } + public function testUnmatchedIs404(): void { + $r = new Router(); + $this->assertSame(404, $r->dispatch(new Request('GET', '/nope', [], '', [], []))->status()); + } + public function testMethodMismatchIs404(): void { + $r = new Router(); + $r->add('POST', '/x', fn() => Response::text('ok')); + $this->assertSame(404, $r->dispatch(new Request('GET', '/x', [], '', [], []))->status()); + } +}