在Heroku上使用Postman测试Express POST接口出现列不存在、Cannot Post报错
问题根因与排查方案
前置验证:既然项目的GET请求可正常调用,说明Heroku部署状态、Postgres连接配置、Express基础路由服务都是正常运行的,两类报错的问题完全出在POST接口的实现逻辑和测试配置上。
两类报错的对应原因
1. 报错 column "test2" does not exist
该问题来自SQL语句的构造缺陷:
- 现有代码通过字符串拼接的方式把路径参数直接塞进SQL查询,没有给字符串类型的参数加单引号包裹,也没有做安全转义
- 拼接完成后的实际SQL逻辑等价于:
INSERT INTO users(...) VALUES (DEFAULT, test2@gmail.com, test, test, ...),Postgres解析时会把没有引号包裹的test2@gmail.com识别为数据库列名,而非可存储的字符串值,自然抛出列不存在的错误 - 这种写法同时存在严重的SQL注入安全风险
2. 报错 Cannot Post
该问题来自路由匹配规则不匹配:
- 后端注册的POST处理路由是
/api/v1/users/:email/:firstName/:lastName,要求必须在路径上依次传入三个参数段才能匹配到处理逻辑 - 测试时直接请求
/api/v1/users?email=xxx&firstName=xxx&lastName=xxx,没有带上路径所需的三个参数段,Express找不到匹配的POST路由,就会直接抛出Cannot Post的默认错误
分步修复方案
第一步:调整接口设计与路由匹配
优先采用符合RESTful规范的实现方式,而非将用户参数硬塞在URL路径中:
- 将POST创建用户的路由调整为
/api/v1/users,不再依赖路径参数传递用户信息,避免路径中出现@、/等特殊字符导致的路由解析问题 - 在Express应用初始化时注册JSON请求体解析中间件,否则无法从请求中读取参数:
// 必须在所有业务路由之前注册 app.use(express.json());
第二步:重构数据库查询逻辑
彻底替换字符串拼接的查询写法,改用pg库支持的参数化查询,既解决字符串解析问题,也规避SQL注入风险:
app.post('/api/v1/users', async (req, res) => { const client = await pool.connect(); try { // 从请求体中读取参数 const { email, firstName, lastName } = req.body; // 用占位符替代直接拼接,参数单独传入,pg库会自动完成转义处理 const result = await client.query( `INSERT INTO users(id, email, first_name, last_name, created_date, last_session) VALUES (DEFAULT, $1, $2, $3, now(), now()) RETURNING *;`, [email, firstName, lastName] ); res.json({ results: result.rows }); } catch (err) { console.error(err); res.status(500).send("Error " + err.message); } finally { // 无论操作成功或失败,都释放数据库连接,避免连接池泄漏 client.release(); } });
注意:原代码中把
now()用单引号包裹成了字符串,会导致数据库存储固定文本而非实际当前时间,需去掉单引号直接使用SQL内置函数即可。
第三步:调整Postman测试配置
按照改造后的接口规则配置请求:
- 请求方法选择POST,请求URL填写
[你的Heroku项目域名]/api/v1/users - 切换到Postman的Body配置面板,选择
raw格式,数据类型设置为JSON,填入测试参数:{ "email": "test2@gmail.com", "firstName": "test", "lastName": "test" } - 不要将参数放在URL的query string(即?后的参数段)或路径段中,否则会出现路由不匹配的
Cannot Post错误
内容的提问来源于stack exchange,提问作者rjdb123
相关产品推荐
相关产品推荐

