[^/]+)', $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)) { // Decode captured params: a camera_id/zone_id with a space or Korean text is // %-encoded in the URL, so without this GET /api/zones/{camera} never matches // what POST /api/zones stored. $params = array_map('rawurldecode', array_filter($m, 'is_string', ARRAY_FILTER_USE_KEY)); return $handler($req, $params); } } return Response::json(['error' => 'not_found'], 404); } }