Laravel默认429响应为HTML,需自定义ApiThrottleRequests中间件重写buildResponse()返回JSON,并在Axios拦截器中统一处理429状态码以展示友好提示。

当用户频繁刷新页面或连续点击按钮触发 API 限流时,Laravel 默认返回裸 HTML 的 429 页面,前端无法捕获结构化错误、无法统一弹窗提示、甚至出现“双重报错”——这直接破坏操作连贯性与信任感。
替换默认 429 响应为 JSON 格式
打开 app/Http/Middleware/ApiThrottleRequests.php(若未创建则先运行 php artisan make:middleware ApiThrottleRequests)。
继承 Illuminate\Routing\ThrottleRequests 并重写 buildResponse() 方法:
在方法内返回 response()->json(['message' => '操作太快啦,请稍后再试'], 429)->header('Content-Type', 'application/json')。
立即学习“前端免费学习笔记(深入)”;
【必须删除父类中 throw new ThrottleRequestsException 的调用】,否则仍会抛出异常并走全局异常处理器路径,JSON 响应不会生效。
为特定路由启用自定义限流中间件
方法一:直接绑定到单个路由
Route::post('/comment', [CommentController::class, 'store'])->middleware(ApiThrottleRequests::class);
方法二:注册为命名中间件别名(推荐)
在 app/Http/Kernel.php 的 $middlewareAliases 数组中添加:'api.throttle' => \App\Http\Middleware\ApiThrottleRequests::class。
之后即可在路由中使用:->middleware('api.throttle')。
前端统一拦截 429 并展示友好提示
第一步:在 Axios 全局响应拦截器中判断状态码
if (error.response?.status === 429) {
第二步:提取响应体中的 message 字段
const msg = error.response.data.message || '请求过于频繁';
第三步:调用 UI 框架的提示方法(以 Element Plus 为例)
ElMessage.error({ message: msg, duration: 2500 });
⚠️ 注意:必须确保业务层代码中 不再重复 catch 并调用 ElMessage.error,否则将出现两个相同提示框。
验证限流响应是否生效
用 curl 手动触发限流:
curl -X POST http://localhost/api/comment -H "Accept: application/json" -H "Authorization: Bearer xxx" -d "content=test" 连续发送 11 次(假设限流设为 10/minute)。
观察第 11 次响应:状态码应为 429,响应体是 JSON 格式,且含 "message": "操作太快啦,请稍后再试"。
检查响应头是否包含 X-RateLimit-Remaining: 0 和 Retry-After: 60 —— 这两项是前端倒计时重试逻辑的关键依据。


















