一、问题介绍
在部署 AI 辅导员系统后端(Laravel 框架)时,遇到一个典型问题:
- 访问http://aiagent.admin.com/(根路径)返回 200 正常;
- 访问http://aiagent.admin.com/api/aicareer/test(API 路由)却返回 404;
- 前端调用所有/api/*接口均失败,直接阻断业务流程。
这种 “根路径可用、子路由 404” 的现象,在 Laravel + Nginx 部署中极为常见,本质是动态路由转发配置缺失或被覆盖。本文将完整还原排查过程、核心配置修改,并提炼可复用的排查模板,帮你快速解决同类问题。
二、项目背景速览
先明确核心环境信息,方便对标自身项目:
- 后端框架:Laravel(项目入口:aiagent_admin/admin/public/index.php);
- 站点配置:域名aiagent.admin.com,Nginx 监听 80 端口;
- 核心路由:
- API 路由:routes/api.php:19-21定义/api/aicareer/*路由组;
- Web 路由:routes/web.php:18-20定义登录视图与接口;
- CORS 策略:config/cors.php默认允许所有来源(allowed_origins=['*'])和请求方法(allowed_methods=['*'])。
三、问题根因:Nginx 路由转发 “偏科”
为什么根路径正常,/api/*却 404?核心原因的拆解:
- Laravel 是单入口框架,所有动态请求(包括/api/*)必须通过public/index.php解析;
- Nginx 默认仅对根路径(/)启用index index.php,但/api/*这类子路径会被当作 “静态资源路径” 查找;
- 若未配置try_files转发规则,Nginx 会直接返回 404,而非交给 Laravel 路由处理。
简单说:Nginx 把/api/aicareer/test当成了 “要读取的静态文件”,而非 “需要框架解析的动态接口”。
四、核心解决方案:统一入口转发 + 冲突排查
解决思路很明确:让Nginx把所有动态请求(根路径 + /api/*)统一转发到 index.php,同时避免其他配置覆盖该规则。
(一)Nginx 配置调整(关键步骤)
核心动作是为location /和/api/添加try_files转发规则,完整配置如下:
server { listen 80; server_name aiagent.admin.com; root /path/to/aiagent_admin/admin/public; #替换为实际项目public目录 index index.php; # 1.根路径转发:所有动态请求交给index.php location / { try_files $uri $uri/ /index.php?$query_string; #避免静态资源404干扰,由Laravel统一处理404 error_page 404 /index.php; } # 2. /api/路径强制转发:^~优先级高于其他location,防止被覆盖 location ^~ /api/ { try_files $uri $uri/ /index.php?$query_string; } # 3. PHP处理段:沿用现有配置(如include php/84.conf),确保只允许合法PHP执行 location ~ \.php$ { include php/84.conf; #替换为你的PHP-FPM配置路径 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # 4.检查冲突配置:避免proxy/rewrite覆盖统一入口 #关键:确保include的proxy/*.conf或rewrite/*.conf中,没有更严格的location规则 include proxy/aiagent.admin.com/*.conf; include rewrite/aiagent.admin.com/*.conf; } |
配置说明:
- try_files $uri $uri/ /index.php?$query_string:Nginx 优先查找静态文件($uri),找不到则查找目录($uri/),最后转发到 index.php 处理动态请求(Laravel 官方推荐写法);
- location ^~ /api/:^~表示 “前缀匹配” 且优先级最高,防止其他location规则(如 proxy/rewrite 中的配置)覆盖/api/转发逻辑;
- 必须检查proxy/*.conf和rewrite/*.conf:很多时候 404 不是主配置的问题,而是被引入的子配置中更具体的location规则覆盖了统一入口。
(二)Laravel 配套校验(确保后端正常解析)
Nginx 转发配置完成后,需校验 Laravel 自身配置,避免 “转发成功但后端处理失败”:
- 路由有效性:确认routes/api.php中/api/aicareer/test路由已定义,示例:
// routes/api.php:19-21 Route::prefix('aicreer')->group(function () { Route::get('test', [AICareerController::class, 'test']); }); |
- CORS策略:默认配置已允许所有来源,若需携带凭据(如 Cookie),需调整config/cors.php:
'supports_credentials' => true, //开启凭据支持 'allowed_origins' => ['https://your-frontend-domain.com'], //替换为具体前端域名(不能用*) |
前端需配合设置fetch或axios的credentials: 'include';
- 入口文件完整性:检查public/index.php:32-55是否正常引导 Laravel 框架(默认无需修改,避免误删核心代码)。
五、日志与环境变量:确保链路可观测 + 连接正常
(一)日志链路配置(快速定位问题)
项目已配置自定义 API 日志通道,需确认以下几点,确保排查时有据可依:
- 日志通道:config/logging.php:144-151定义api通道,日志文件路径:storage/logs/api-YYYY-MM-DD.log;
- 日志格式:app/Libs/Logging/AdviceFormatter.php会输出 `Api:TraceId: 方便追踪请求;
- TraceId 注入:app/Http/Middleware/TraceId.php为每个请求生成唯一 TraceId,TraceIdProcessor.php注入日志;
- 日志触发:只有响应为JsonResponse时,Terminate.php中间件才会写入 API 日志(与Controller::success方法行为相关)。
(二)环境变量与数据库连接(避免 “转发成功但查库失败”)
- 核心.env配置(aiagent_admin/admin/.env:9-14):
DB_HOST=your-db-host #注意:127.0.0.1仅代表本机,远端库需填实际地址 DB_PORT=3306 DB_DATABASE=aiagent_db DB_USERNAME=db_user DB_PASSWORD=db_pass APP_URL=http://aiagent.admin.com #需与域名一致,配合TrustHosts中间件 |
- 额外数据库连接(如zhiyin):若启用config/database.php:67-85中的配置,需补充ZHIYIN_DB_*环境变量;
- VPN 与连接策略:
- 直接连远端库:DB_HOST填公司提供的远端 DB 地址(非 127.0.0.1);
- 端口转发:通过ssh -L 3306:>:3306 <user>@>将远端库映射到本机,再用DB_HOST=127.0.0.1。
六、验证与排错:三步确认问题解决
(一)Nginx 层面验证
# 1.验证根路径正常 curl -I http://aiagent.admin.com/ #应返回200 OK # 2.验证API路由不再404 curl -sS -o /dev/null -w "%{http_code}\n" http://aiagent.admin.com/api/aicareer/test #应返回200或业务响应码(非404) # 3.检查Nginx错误日志 cat D:/BtSoft/wwwlogs/aiagent.admin.com.error.log #无“file not found”类错误 |
(二)Laravel 层面验证
# 1.清理配置缓存 php artisan config:clear # 2.用tinker验证数据库连接与表存在 php artisan tinker > App\Models\Admin\ManagerModel::count() #应返回表记录数(无报错) > App\Models\MenuModel::count() #验证业务表可访问 |
(三)日志层面验证
打开storage/logs/api-YYYY-MM-DD.log,确认:
- 存在Api:/api/aicareer/test记录(说明请求被框架处理);
- 存在 `TraceId: 链路追踪正常);
- 无数据库连接错误、权限错误等日志。
七、常见坑点(避坑指南)
- 缺少 try_files配置:最核心坑点,导致/api/*被当作静态资源,直接 404;
- 配置被覆盖:proxy/*.conf或rewrite/*.conf中的location规则优先级更高,覆盖了统一入口转发;
- 数据库连接错误:.env中DB_HOST填错(如用 127.0.0.1 指向远端库)、账号无权限;
- VPN连接误区:误以为127.0.0.1是远端库,实际需填远端地址或做端口转发;
- 日志不触发:Controller::success返回视图而非 JSON,导致 API 日志未写入(需确保接口返回JsonResponse)。
八、总结:可复用的排查模板
遇到 “前端无法访问 Laravel 后端” 问题时,按以下流程排查,高效解决:
- 验证现象:根路径 vs /api/* 路径响应码对比(是否 404);
- 检查 Nginx转发:确保location /和/api/配置try_files $uri $uri/ /index.php?$query_string,且无配置覆盖;
- 校验 Laravel配置:路由定义、CORS 策略、.env数据库连接;
- 日志排查:Nginx 错误日志 + Laravel API 日志,定位转发 / 数据库 / 业务错误;
- 数据库验证:用 tinker 测试表访问,确认连接正常。
这套模板可直接复用到所有 Laravel + Nginx 项目,后续可进一步优化:
- 统一 rewrite 策略,避免配置冲突;
- 细化 CORS 规则(拒绝 *,指定具体域名);
- 收敛日志噪声,增加告警机制;
- 固化 Nginx 配置模板,同类项目直接复用。
通过以上步骤,不仅能解决 “前端无法访问后端” 的问题,还能提升项目的可观测性和生产稳定性,为后续维护打下基础。