Angular与Lumen PUT请求通信失败(405方法不允许)求助
解决Lumen PUT请求返回405 Method Not Allowed的问题
Hey,我来帮你排查下这个PUT请求返回405的问题——我之前在做Lumen+Angular的项目时也踩过类似的坑,大概率是路由配置、中间件顺序或者CORS处理的问题,咱们一步步拆解:
1. 先确认Lumen的路由是不是配对了
首先得检查routes/api.php(或者routes/web.php,看你把API路由放哪了)里的PUT路由是不是正确注册了。比如如果是更新单条博客,路由应该是这样的:
$router->put('/api/blog/{id}', 'BlogController@update');
要注意三个点:
- 必须用
put()方法,不能写成post()或者其他; - 路由路径要和Angular请求的完全一致——比如你Angular请求的是
/api/blog不带ID,但路由定义成带{id}的,就会匹配不上返回405; - 控制器的
update方法确实存在,而且没有拼写错误。
2. 检查CORS中间件的配置和执行顺序
你说已经写了CORS中间件,但这里容易踩三个坑:
坑1:CORS中间件有没有全局注册?
在bootstrap/app.php里,要把CORS中间件加到全局中间件数组里,确保所有请求都先经过它:
$app->middleware([ App\Http\Middleware\CorsMiddleware::class, ]);
如果只在某个路由组里加,那OPTIONS预检请求可能走不到这个中间件。
坑2:有没有正确处理OPTIONS预检请求?
PUT属于非简单请求,浏览器会先发OPTIONS请求确认跨域权限。你的CORS中间件必须直接响应OPTIONS请求,不能让它走到路由匹配或者JWT验证环节。比如中间件代码应该是这样的:
public function handle($request, Closure $next) { $headers = [ 'Access-Control-Allow-Origin' => 'your-angular-domain.com', // 生产环境别用*,指定具体域名 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers' => 'Content-Type, Authorization', ]; // 直接响应OPTIONS请求 if ($request->isMethod('OPTIONS')) { return response()->json('OK', 200, $headers); } // 处理其他请求 $response = $next($request); foreach ($headers as $key => $value) { $response->header($key, $value); } return $response; }
坑3:中间件顺序是不是搞反了?
CORS中间件必须放在JWT中间件前面!如果JWT先执行,OPTIONS请求因为没有带Token,会直接被拦截返回401,浏览器就会误以为是跨域不允许,间接返回405的错误。
3. 排查JWT中间件的问题
如果你的PUT路由用了JWT认证,要确认两个点:
- Angular的请求是不是正确带上了Token?比如在请求头里加
Authorization: Bearer {your-token},代码大概是这样:
const authHeaders = new HttpHeaders({ 'Authorization': `Bearer ${this.jwtToken}`, 'Content-Type': 'application/json' }); this.http.put('/api/blog/1', yourBlogData, { headers: authHeaders }).subscribe(...)
- JWT中间件有没有排除OPTIONS请求?如果没有,OPTIONS请求会因为没有Token被拒绝,同样会导致浏览器报错。
4. 检查Web服务器的配置
如果上面都没问题,就得看看Apache/Nginx是不是限制了PUT方法:
- 对于Apache:确保
mod_rewrite开启,而且.htaccess文件里没有限制HTTP方法,默认的Lumen.htaccess应该包含处理Authorization头的规则,别删了:
<IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews </IfModule> RewriteEngine On # 必须保留这个,处理JWT的Authorization头 RewriteCond %{HTTP:Authorization} . RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)/$ /$1 [L,R=301] RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] </IfModule>
- 对于Nginx:要在location块里明确允许PUT方法,并且单独处理OPTIONS请求:
location / { try_files $uri $uri/ /index.php?$query_string; add_header Access-Control-Allow-Origin your-angular-domain.com; add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS'; add_header Access-Control-Allow-Headers 'Content-Type, Authorization'; # 直接响应OPTIONS请求 if ($request_method = OPTIONS) { return 204; } }
最后一步:用Postman调试排除Angular的问题
可以先跳过Angular,用Postman直接发PUT请求到http://your-domain/api/blog/{id},带上正确的Token和请求体:
- 如果Postman也返回405,那问题肯定在Lumen端,再回头检查路由和中间件;
- 如果Postman能成功,那就是Angular的请求配置有问题——比如路径写错了,或者请求头没带对。
应该能解决你的问题啦!
内容的提问来源于stack exchange,提问作者Lars
相关产品推荐
相关产品推荐

