如何在Node.js+Express中针对路由错误HTTP方法返回错误状态
Express API中处理错误HTTP方法的方案
问题描述
我是Node.js新手,正在开发API,想实现:当用户对路由使用错误的HTTP方法(比如应该用GET却用了PUT)时,API返回明确的错误信息和405状态码。
我尝试过添加method-override和全局中间件,但放在路由引入前会拦截所有请求,放在后面又没有效果,Node.js版本为v19.3.0。
我的相关代码
路由文件
const router = require('express').Router(); const controller = require('../controllers/users.controller') router.get('/', controller.getAll); router.get('/actives', controller.getAllActive); router.get('/:id', controller.getById); router.post('/register', controller.create); router.post('/auth', controller.authenticate); router.put('/:id', controller.update); router.put('/:id/activate', controller.activate); router.put('/:id/deactivate', controller.deactivate); module.exports = router
服务器文件
const express = require('express'); const cors = require('cors'); require('dotenv').config(); const server = express(); const port = process.env.PORT; server.use(cors()); server.use(express.urlencoded({ extended: false })) server.use(express.json()); const usersRouter = require('./routes/users.router'); server.use('/api/v1/users', usersRouter); server.listen(port, (err) => { if (err) { console.log("error while starting server"); } else { console.log(`Server running at http://localhost:${port}/`); } });
控制器getAllActive方法
getAllActive: async (req, res) => { try { const allActiveUsers = await prisma.user.findMany({ where: { active: true } }); res.json({ message: "Done", data: allActiveUsers }); } catch (error) { console.log(error); res.status(500).json({ message: "Error" }); } },
之前尝试的无效代码
const methodOverride = require('method-override'); server.use(methodOverride('_method')); server.use((req, res, next) => { res.status(405).json({ message: req.method + ' method not allowed on ' + req.originalUrl + ' route.' }); });
解决方案
方法1:在路由文件末尾添加405处理中间件
修改你的路由文件,在所有路由定义之后添加一个all方法的中间件,用来捕获当前路由下路径存在但HTTP方法不匹配的请求:
const router = require('express').Router(); const controller = require('../controllers/users.controller') // 原有的路由定义 router.get('/', controller.getAll); router.get('/actives', controller.getAllActive); router.get('/:id', controller.getById); router.post('/register', controller.create); router.post('/auth', controller.authenticate); router.put('/:id', controller.update); router.put('/:id/activate', controller.activate); router.put('/:id/deactivate', controller.deactivate); // 新增:处理当前路由下的405情况 router.all('*', (req, res, next) => { let allowedMethods = []; // 遍历路由栈,找出当前路径支持的所有HTTP方法 router.stack.forEach(layer => { if (layer.route && layer.route.path === req.path) { allowedMethods = Object.keys(layer.route.methods); } }); if (allowedMethods.length > 0) { // 路径存在但方法不允许,返回405 res.status(405).json({ message: `${req.method} 方法不允许访问 ${req.originalUrl} 路由`, allowedMethods: allowedMethods.map(method => method.toUpperCase()) }); } else { // 路径不存在,交给全局404中间件处理 next(); } }); module.exports = router
方法2:添加全局404中间件(可选)
在服务器文件的最后添加全局404处理,区分“路径不存在”和“方法不允许”的情况:
// 放在server.listen之前 server.use((req, res) => { res.status(404).json({ message: `路径 ${req.originalUrl} 不存在` }); });
说明
method-override是用来处理HTML表单无法发送PUT/DELETE请求的场景,和你的需求无关,可以直接移除。- 上述方案会在用户使用错误方法时返回405状态码,同时告知允许的HTTP方法,提升API的友好性。
内容的提问来源于stack exchange,提问作者belinda.g.freitas
相关产品推荐
相关产品推荐

