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()); + } +}