使用Express+Serverless+API Gateway更新DynamoDB时出现500错误
排查Express+Serverless+API Gateway更新患者接口500错误的方案
1. 控制器参数顺序完全颠倒
Express的控制器/中间件参数顺序固定为(req: Request, res: Response),你当前代码把参数写反成(res: Response, req: Request),这会导致所有请求对象操作失效(比如拿不到req.params.id),调用响应方法时也会因上下文错误抛出异常,直接触发500错误。
修复后的控制器代码:
import { Response, Request } from 'express'; import { updatePatientsService } from '../../services/patients/updatePatientsService'; import { getPatientsByIdService } from '../../services/patients/getPatientsByIdService'; // 修正拼写错误 const updatePatientsController = async (req: Request, res: Response) => { // 交换req和res顺序 const { id } = req.params; try { const { Item: patient } = await getPatientsByIdService(id); if (!patient) return res.status(404).send('patient not found'); // 合并路由参数的id到请求体,确保DynamoDB能定位到要更新的条目 const updatedPatient = await updatePatientsService({ ...req.body, id }); return res.status(200).json(updatedPatient); } catch (error) { console.error('更新患者失败:', error); return res.status(500).send('服务器内部错误'); } }; export { updatePatientsController };
2. 服务层的潜在问题
2.1 未确保更新对象包含主键
DynamoDB的put操作需要主键(假设id是你的表主键),如果仅传入req.body,可能因缺少主键导致创建新条目而非更新原有数据,甚至触发数据库错误。必须将路由参数中的id合并到更新对象中。
2.2 缺少环境变量校验与错误捕获
process.env.PATIENTS_TABLE未配置时,非空断言!会直接抛出运行时错误;同时dynamoClient.put()的异常未被捕获,会直接向上抛出导致500。
修复后的服务层代码:
import AWS from 'aws-sdk'; import { Patient } from '../../types/interfaces/Patient'; const dynamoClient = new AWS.DynamoDB.DocumentClient(); const tableName = process.env.PATIENTS_TABLE; // 提前校验环境变量,避免后续操作报错 if (!tableName) { throw new Error('未配置PATIENTS_TABLE环境变量'); } const updatePatientsService = async (patient: Patient) => { // 校验主键是否存在 if (!patient.id) { throw new Error('更新患者必须提供id'); } const params = { TableName: tableName, Item: { ...patient, }, }; try { await dynamoClient.put(params).promise(); return patient; // 返回更新后的患者信息 } catch (error) { console.error('DynamoDB更新操作失败:', error); throw error; // 抛出错误让上层控制器统一处理 } }; export { updatePatientsService };
3. 拼写错误导致的导入失败
控制器中导入的getPatientsByIdSerive存在拼写错误(应为getPatientsByIdService),如果服务层导出的函数名正确,这个拼写错误会导致运行时找不到函数,抛出异常触发500,必须修正拼写。
4. 缺少请求参数校验
创建接口使用了celebrate(patientValidator)做参数校验,但更新接口未添加,不符合Patient类型的请求体直接进入服务层可能触发数据库错误。给PUT接口加上校验:
// 路由代码修改 routes.put('/:id', celebrate(patientValidator), updatePatientsController);
5. Serverless环境日志排查
若以上修复后仍有问题,通过以下方式查看日志定位错误:
- 用Serverless CLI执行
serverless logs -f <你的函数名> -t实时查看函数运行日志 - 检查API Gateway的执行日志,获取具体错误堆栈信息
内容的提问来源于stack exchange,提问作者guilherme augusto
相关产品推荐
相关产品推荐

