如何在ExpressJS路由中用正则验证计算器API的请求路径有效性?
Express计算器API的正则路由校验方案
要实现符合要求的路径校验,你可以通过正则表达式路由精确匹配合法路径,同时按顺序设置不同的路由来区分不同的错误场景,返回对应的响应。
核心正则规则与路由实现
1. 匹配合法完整路径的正则
使用带命名捕获组的正则,可以直接从req.params中提取运算符和操作数,清晰直观:
/^\/api\/calculator\/(?<operator>add|subtract|multiply|divide)\/(?<number1>-?\d+(\.\d+)?)\/(?<number2>-?\d+(\.\d+)?)$/
正则各部分说明:
^\/api\/calculator\/:锁定路径前缀,确保请求从api/calculator开始(?<operator>add|subtract|multiply|divide):命名捕获组,精确匹配仅有的4种合法运算符(?<number1>-?\d+(\.\d+)?):匹配整数/小数格式的操作数,支持负号(-?),\d+(\.\d+)?覆盖整数(如123)和标准小数(如45.67)$:确保路径结尾无多余字符,避免api/calculator/add/1/2/这类多斜杠的无效路径
2. 完整代码示例
const express = require('express'); const app = express(); // 处理合法请求的核心路由 app.get(/^\/api\/calculator\/(?<operator>add|subtract|multiply|divide)\/(?<number1>-?\d+(\.\d+)?)\/(?<number2>-?\d+(\.\d+)?)$/, (req, res) => { const { operator, number1, number2 } = req.params; const num1 = parseFloat(number1); const num2 = parseFloat(number2); let result; switch(operator) { case 'add': result = num1 + num2; break; case 'subtract': result = num1 - num2; break; case 'multiply': result = num1 * num2; break; case 'divide': if (num2 === 0) { return res.status(400).json({ error: '除数不能为0' }); } result = num1 / num2; break; } res.json({ operator, num1, num2, result }); }); // 捕获运算符非法但路径结构完整的请求 app.get(/^\/api\/calculator\/[^\/]+\/(-?\d+(\.\d+)?)\/(-?\d+(\.\d+)?)$/, (req, res) => { res.status(400).json({ error: '运算符无效,请使用add、subtract、multiply或divide' }); }); // 捕获操作数缺失的请求(如仅提供运算符、或仅一个操作数) app.get(/^\/api\/calculator\/(add|subtract|multiply|divide)(?:\/(-?\d+(\.\d+)?))?$/, (req, res) => { res.status(400).json({ error: '操作数无效,请提供两个合法的数字操作数' }); }); // 兜底处理所有其他/api/calculator开头的无效路径 app.all('/api/calculator/*', (req, res) => { res.status(400).json({ error: '请求路径格式错误,请遵循api/calculator/:operator/:number1/:number2格式' }); }); app.listen(3000, () => { console.log('计算器API运行在3000端口'); });
关键注意事项
- 路由顺序:Express按代码顺序匹配路由,务必把精确匹配的合法路由放在最前面,避免被兜底路由提前捕获。
- 数字格式调整:如果需要更严格的数字校验(比如不允许
.123或123.这类格式),可以把操作数的正则改成-?(?:\d+\.\d+|\d+),只匹配标准整数和小数。 - 请求方法扩展:如果需要支持POST/PUT等方法,把
app.get替换为app.post或app.all即可。
内容的提问来源于stack exchange,提问作者mogale
相关产品推荐
相关产品推荐

