Laravel 9中Swagger返回HTML页面而非验证错误问题
问题解决:Swagger触发Laravel验证时返回HTML而非JSON
问题场景
Laravel 9项目中配置Swagger后,接口传入正确参数时运行正常;但传入错误参数触发验证时,Postman可正常返回验证错误的JSON响应,而Swagger却返回HTML页面。
Swagger注解代码
/** * @OA\Put( * path="/api/admins/{id}/status", * operationId="updateAdminStatus", * tags={"Admin"}, * security={ {"sanctum": {} }}, * summary="Update admin status", * description="Update an existing admin user's status by ID", * @OA\Parameter( * name="id", * in="path", * required=true, * description="Admin ID", * @OA\Schema(type="integer", format="int32", example=1) * ), * @OA\RequestBody( * required=true, * description="Pass admin data", * @OA\JsonContent( * required={"status"}, * @OA\Property(property="status", type="integer", format="int32", example=0) * ) * ), * @OA\Response( * response=200, * description="Admin status updated successfully" * ), * @OA\Response( * response=400, * description="Invalid input data" * ), * @OA\Response( * response=401, * description="Unauthenticated" * ), * @OA\Response( * response=404, * description="Admin not found" * ), * @OA\Response( * response=500, * description="Internal server error" * ) * ) */
验证代码
$validatedData = $request->validate([ 'status' => 'required|in:0,1' ]); throw_unless($validatedData);
响应对比
- Postman响应:
{ "message": "The status field is required.", "errors": { "status": [ "The status field is required." ] } }
- Swagger响应:返回HTML错误页面
问题原因
Laravel的默认验证异常处理会根据请求的Accept头判断响应格式:
- Postman发送的请求
Accept头为application/json,所以返回JSON格式错误 - Swagger UI发送的请求
Accept头包含text/html,Laravel因此返回了HTML错误页面
解决方案
方案1:局部修改验证逻辑(单接口)
放弃$request->validate()的自动异常抛出,改用Validator facade手动验证并强制返回JSON响应:
use Illuminate\Support\Facades\Validator; // 手动创建验证器 $validator = Validator::make($request->all(), [ 'status' => 'required|in:0,1' ]); // 验证失败时返回JSON if ($validator->fails()) { return response()->json([ 'message' => 'Invalid input data', 'errors' => $validator->errors() ], 400); } // 验证通过后继续业务逻辑 $validatedData = $validator->validated();
方案2:全局修改API路由的异常响应(所有接口)
在app/Exceptions/Handler.php中添加验证异常的自定义处理,针对API路由强制返回JSON:
use Illuminate\Validation\ValidationException; public function register() { $this->renderable(function (ValidationException $e, $request) { // 判断当前请求是否为API路由 if ($request->is('api/*')) { return response()->json([ 'message' => $e->getMessage(), 'errors' => $e->errors() ], $e->status); } }); }
补充说明
如果使用Laravel Sanctum且Swagger已配置正确的认证,上述方案即可解决问题。无需额外在验证逻辑中添加try-catch,因为$request->validate()本身会自动抛出ValidationException,我们只需修改该异常的响应格式即可。
内容的提问来源于stack exchange,提问作者Michalle Rodriguez
相关产品推荐
相关产品推荐

