Lumen POST无尾斜杠根路由301跳转GET异常问题求解
问题根因
修改.htaccess不生效的核心原因:根路径POST触发的301重定向不是Apache重写规则导致的,是Lumen框架自带RedirectTrailingSlash中间件的已知逻辑缺陷。该中间件处理根路径时不会校验请求方法,直接将无尾斜杠的请求返回301重定向到带尾斜杠的地址,而客户端收到301状态码后默认会把非GET请求转为GET再发起跳转,最终造成原请求方法、请求体全部丢失。
非根路径无此问题,是因为非根路径的尾斜杠匹配逻辑会正确识别请求类型,不会误触发重定向。
推荐解决方案:自定义中间件替换默认逻辑(一劳永逸)
- 新建自定义中间件文件
app/Http/Middleware/RedirectTrailingSlash.php,重写尾斜杠处理逻辑,对根路径直接放行,非根路径仅对GET请求执行尾斜杠重定向:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class RedirectTrailingSlash { public function handle(Request $request, Closure $next) { $uri = $request->getRequestUri(); // 根路径直接放行,不做尾斜杠重定向 if (in_array($uri, ['/', ''], true)) { return $next($request); } // 非根路径仅处理GET请求的尾斜杠重定向 if (str_ends_with($uri, '/') && $request->isMethod('GET')) { return redirect(rtrim($uri, '/'), 301); } return $next($request); } }
- 打开框架启动文件
bootstrap/app.php,在全局中间件配置段注释掉框架默认的尾斜杠中间件,替换为刚才新建的自定义中间件:
// 注释原框架自带的尾斜杠中间件 // $app->middleware([ // ... // \Laravel\Lumen\Http\Middleware\RedirectTrailingSlash::class, // ... // ]); // 注册自定义中间件,其他原有全局中间件保持不变 $app->middleware([ \App\Http\Middleware\RedirectTrailingSlash::class, // 其他原有全局中间件按原顺序保留 ]);
- 路由配置保持原有写法即可,无需调整:
$router->get("/", "ApiModule@list"); $router->get("/{id}", "ApiModule@read"); $router->post("/", "ApiModule@create"); $router->put("/{id}", "ApiModule@update"); $router->delete("/{id}", "ApiModule@delete");
- 重启PHP服务,清理所有客户端缓存的301重定向记录:Postman需清除请求缓存,浏览器需清空对应站点缓存(301是永久重定向,会被客户端本地长期缓存,不清理会导致测试结果不符合预期)。
配置完成后,根路径的POST请求无论是否携带尾斜杠,都可以正常命中创建课程的接口逻辑,不会再出现重定向转GET的问题。
快速兼容备选方案
如果暂时不想修改中间件,可以在路由文件中同时注册空路径和/路径的POST路由,指向同一个控制器方法,同时保留之前在.htaccess中添加的RewriteCond %{REQUEST_METHOD} GET规则:
$router->get("/", "ApiModule@list"); $router->get("/{id}", "ApiModule@read"); $router->post("/", "ApiModule@create"); // 新增空路径POST路由,指向同一个处理方法 $router->post("", "ApiModule@create"); $router->put("/{id}", "ApiModule@update"); $router->delete("/{id}", "ApiModule@delete");
注意:该方案稳定性不如自定义中间件方案,优先选择第一种方案。
内容的提问来源于stack exchange,提问作者RBFraphael
相关产品推荐
相关产品推荐

