API错误处理在Postman正常 PHP客户端抛出异常求助
问题描述
我的API错误处理逻辑在Postman中能返回清晰易懂的友好错误信息,但集成到PHP客户端(使用Guzzle库)时,总是抛出异常,且获取的响应不规整。
后端相关实现代码
工具类ErrorResponse
class ErrorResponse extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; Error.captureStackTrace(this, this.constructor); } } module.exports = ErrorResponse;
错误中间件errorHandler
const ErrorResponse = require('../Utils/errorResponse'); const errorHandler = (err, req, res, next) => { let error = { ...err }; error.message = err.message; // Log to console for dev console.log(err); // console.log(err.response.data); // Mongoose bad ObjectId if (err.name === 'CastError') { const message = `Resource not found`; error = new ErrorResponse(message, 404); } // Mongoose duplicate key if (err.code === 11000) { const message = 'Duplicate field value entered'; error = new ErrorResponse(message, 400); } // Mongoose validation error if (err.name === 'ValidationError') { const message = Object.values(err.errors).map(val => val.message); error = new ErrorResponse(message, 400); } res.status(error.statusCode || 500).json({ "status": "error", "message": error.message || 'Server Error' }); }; module.exports = errorHandler;
错误调用示例
return next(new ErrorResponse('Invalid credentials', 401));
PHP端Guzzle代码
try { // 此处是Guzzle请求逻辑 } catch (GuzzleHttp\Exception\ClientException $e) { return $e->getResponse(); }
解决方案
问题核心在于Guzzle会对4xx/5xx状态码的响应自动抛出异常,但你的API确实返回了结构化的错误JSON,只是需要在异常中正确解析响应体,而不是直接返回整个响应对象。
步骤1:正确解析Guzzle异常中的响应体
修改PHP端的catch逻辑,获取并解析响应的JSON内容:
try { $client = new GuzzleHttp\Client(); $response = $client->request('POST', 'your-api-endpoint', [ // 请求参数配置(如headers、form_params等) ]); // 处理正常响应 $data = json_decode($response->getBody(), true); } catch (GuzzleHttp\Exception\ClientException $e) { // 获取4xx错误的状态码和响应体 $statusCode = $e->getResponse()->getStatusCode(); $errorBody = $e->getResponse()->getBody()->getContents(); // 解析为关联数组 $errorData = json_decode($errorBody, true); // 返回结构化的错误信息 return [ 'status' => 'error', 'code' => $statusCode, 'message' => $errorData['message'] ?? 'Unknown error' ]; } catch (GuzzleHttp\Exception\ServerException $e) { // 处理5xx服务器错误 $errorBody = $e->getResponse()->getBody()->getContents(); $errorData = json_decode($errorBody, true); return [ 'status' => 'error', 'code' => $e->getResponse()->getStatusCode(), 'message' => $errorData['message'] ?? 'Server error' ]; }
步骤2:后端额外检查(可选)
确保错误中间件的有效性:
- 确认
errorHandler中间件在Express应用中注册在所有路由之后,否则无法捕获路由抛出的异常 - 验证自定义
ErrorResponse实例的属性是否被正确传递,比如在中间件中打印error对象确认statusCode和message是否存在 - 可以在中间件末尾添加日志,输出返回的错误JSON,验证格式是否符合预期:
// 在errorHandler的res.status().json()前添加 const errorResponse = { "status": "error", "message": error.message || 'Server Error' }; console.log('Error response sent:', JSON.stringify(errorResponse)); res.status(error.statusCode || 500).json(errorResponse);
关键说明
- Guzzle将4xx状态码归为
ClientException,5xx归为ServerException,分开捕获能更精准处理不同类型的错误 getBody()->getContents()会一次性读取响应体内容,若后续需要再次读取,需调用$e->getResponse()->getBody()->rewind()重置指针- 解析JSON时传入第二个参数
true,将JSON对象转为PHP关联数组,方便直接取值
内容的提问来源于stack exchange,提问作者Shamsuddeen Omacy
相关产品推荐
相关产品推荐

