Hyperf 返回404最常见原因是static_handler_locations配置为['/']等泛匹配路径导致Swoole直接拦截所有请求、注解路由未被扫描(路径/命名/缓存问题)或curl请求构造不准确(端口、斜杠、参数格式等),三者覆盖生产80%以上404场景。

Hyperf 返回 404,90% 不是路由没写,而是请求根本没进到路由层——它被 Swoole 静态路径拦截、端口错位、注解未扫描或 curl 构造不准确直接挡在了门外。
检查 static_handler_locations 是否劫持了所有路径
这是 Hyperf 项目里最隐蔽也最高频的 404 原因。只要 config/autoload/server.php 中 static_handler_locations 的值包含 ['/'] 或 ['/metrics'],Swoole 就会跳过全部路由匹配,把所有请求当静态文件处理,一律返回 404。
- 打开
config/autoload/server.php,搜索static_handler_locations - 如果值是
['/']、['/metrics']或其他泛匹配路径,直接删掉整行或注释掉 - 改完必须重启服务:
php bin/hyperf.php stop && php bin/hyperf.php start - 特别注意:Hyperf 2.x 和 3.x 在 Swoole 4.5+ 下对此配置极其敏感,哪怕只配了
/,整个 API 层都会失效
确认注解路由是否真被扫描并注册
写了 #[Controller] 却 404,大概率是类压根没被扫描到,不是语法错,而是路径漏了、缓存没刷、或命名不合规。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 检查控制器文件路径是否在
config/autoload/annotations.php的scan.paths列表中,例如:BASE_PATH . '/app/Controller'(不能写成app/Controller) - 确保类名以
Controller结尾(如UserController),否则#[AutoController]不生效 - PHP 8 注解必须用命名参数:
#[Controller(prefix: '/api')],不是#[Controller('/api')] - 改完配置后必须执行:
php bin/hyperf.php di:init-proxy,否则新路径不会生效 - Docker 构建时,
runtime/container/目录不能被.dockerignore过滤掉
用 curl -v 精确验证请求是否抵达路由层
浏览器会自动补斜杠、重定向、加缓存头,掩盖真实问题。404 是连接失败?Swoole 拒绝?还是框架返回?必须靠 curl -v 分清。
- 查端口是否真在监听:
netstat -tuln | grep :9501(Linux/macOS)或netstat -ano | findstr :9501(Windows) - GET 请求带参数必须用单引号包裹 URL:
curl -v 'http://127.0.0.1:9501/user?id=123',否则 shell 会截断& - POST JSON 必须显式指定类型:
curl -X POST -H "Content-Type: application/json" -d '{"name":"test"}' http://127.0.0.1:9501/user - 路径末尾斜杠敏感:
/user/list注册了,访问/user/list/就是 404(除非启用 trailing slash 处理) -
curl -v输出里看第一行响应码和Connection #0 to host是否建立成功,能立刻区分是网络层、Swoole 层还是框架层问题
手动挂载 /metrics 等特殊端点
Hyperf 的 /metrics 默认不注册路由,即使 hyperf/metric 组件已启用、Prometheus 驱动配置正确,也必须手动加一条 Router::get()。
- 在
config/routes.php或启动引导文件中添加:Router::get('/metrics', function () { return ''; })->middleware(PrometheusMiddleware::class); - 路径必须与
config/autoload/metric.php中的scrape_path完全一致(默认就是/metrics) - 闭包函数体里只写
return '',别输出内容,响应由中间件生成 - 切勿用
Router::addRoute()或其他非常规方式,避免路由优先级冲突
真正难排查的 404,往往卡在「你以为它该进路由,其实它连 Swoole 的 HTTP 入口都没摸到」——static_handler_locations、端口错位、注解未扫描这三处,覆盖了生产环境 80% 以上的路由 404 场景。别急着翻路由文档,先跑一遍这三条检查链。


















