You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+Express+Prisma任务系统创建任务报错:Cannot POST /api/v2/tasks/

问题排查:Cannot POST /api/v2/tasks/

我正在使用Node.js、Express和Prisma开发一个任务管理系统,已编写TaskController处理CRUD操作。员工的创建与查询功能运行正常,但尝试创建任务时出现错误:Cannot POST /api/v2/tasks/。

相关代码文件

task.controller.js

const TaskRepository = require("../repositories/task.repository");
const { ApiResponse } = require("../utils/api-response");
const { ApiError } = require("../utils/api-error");

class TaskController {
  constructor() {
    this.repository = new TaskRepository();
  }

  async getAllTasks(req, res, next) {
    try {
      const tasks = await this.repository.findAll();
      res.json(new ApiResponse(200, "Tasks retrieved", tasks));
    } catch (error) {
      next(error);
    }
  }

  async getTaskById(req, res, next) {
    try {
      const id = parseInt(req.params.id);
      const task = await this.repository.findById(id);
      res.json(new ApiResponse(200, "Task retrieved", task));
    } catch (error) {
      next(error);
    }
  }

  async getTasksByEmployee(req, res, next) {
    try {
      const employeeId = parseInt(req.params.employeeId);
      const tasks = await this.repository.findByEmployeeId(employeeId);
      res.json(new ApiResponse(200, "Tasks for employee retrieved", tasks));
    } catch (error) {
      next(error);
    }
  }

  async createTask(req, res, next) {
    try {
      const task = await this.repository.create(req.body);
      res.status(201).json(new ApiResponse(201, "Task created", task));
    } catch (error) {
      next(error);
    }
  }

  async updateTask(req, res, next) {
    try {
      const id = parseInt(req.params.id);
      const updatedTask = await this.repository.update(id, req.body);
      res.json(new ApiResponse(200, "Task updated", updatedTask));
    } catch (error) {
      next(error);
    }
  }

  async deleteTask(req, res, next) {
    try {
      const id = parseInt(req.params.id);
      await this.repository.delete(id);
      res.json(new ApiResponse(200, "Task deleted"));
    } catch (error) {
      next(error);
    }
  }
}

module.exports = TaskController;

task.repository.js

const prisma = require("../prisma/prisma.service");
const { ApiError } = require("../utils/api-error");

class TaskRepository {
  async findAll() {
    try {
      return await prisma.task.findMany({ include: { employee: true } });
    } catch (error) {
      throw new ApiError(500, "Error fetching tasks", [error]);
    }
  }

  async findById(id) {
    try {
      const task = await prisma.task.findUnique({ 
        where: { id }, 
        include: { employee: true } 
      });

      if (!task) {
        throw new ApiError(404, "Task not found");
      }

      return task;
    } catch (error) {
      if (error instanceof ApiError) throw error;
      throw new ApiError(500, "Error fetching task", [error]);
    }
  }

  async findByEmployeeId(employeeId) {
    try {
      return await prisma.task.findMany({ 
        where: { employeeId: parseInt(employeeId) },
        include: { employee: true }
      });
    } catch (error) {
      throw new ApiError(500, "Error fetching employee's tasks", [error]);
    }
  }

  async create(data) {
    try {
      console.log(" Data passed to create task:", data); // Debugging
      return await prisma.task.create({ data });
    } catch (error) {
      throw new ApiError(400, "Error creating task", [error]);
    }
  }

  async update(id, data) {
    try {
      console.log(" Data passed to update task:", data); // Debugging
      return await prisma.task.update({ 
        where: { id }, 
        data 
      });
    } catch (error) {
      throw new ApiError(400, "Error updating task", [error]);
    }
  }

  async delete(id) {
    try {
      return await prisma.task.delete({ where: { id } });
    } catch (error) {
      throw new ApiError(400, "Error deleting task", [error]);
    }
  }
}

module.exports = new TaskRepository();

task.routes.js

// task.routes.js
const express = require("express");
const TaskController = require("../controllers/task.controller");

const router = express.Router();
const taskController = new TaskController();

// Use arrow functions for route handlers (like employee.routes.js)
router.get("/", (req, res, next) => taskController.getAllTasks(req, res, next));
router.get("/:id", (req, res, next) => taskController.getTaskById(req, res, next));
router.post("/", (req, res, next) => taskController.createTask(req, res, next)); //  Fixed
router.put("/:id", (req, res, next) => taskController.updateTask(req, res, next));
router.delete("/:id", (req, res, next) => taskController.deleteTask(req, res, next));

console.log(" Task routes registered:", router.stack.map(r => r.route?.path).filter(Boolean));

module.exports = router;

server.js

const express = require("express");
const cors = require("cors");

const vatRoutes = require("./routes/vat.routes"); // VAT routes
const employeeRoutes = require("./routes/employees.routes"); // Employee routes
const taskRoutes = require("./routes/task.routes"); // Task routes

const app = express();

//  Middleware
app.use(cors()); // Prevent CORS issues
app.use(express.json()); // Parse JSON requests

//  Debugging middleware (logs all requests)
app.use((req, res, next) => {
  console.log(` Received request: ${req.method} ${req.url}`);
  next();
});

//  API Routes
app.use("/api/v1/vat", vatRoutes);
app.use("/api/v1/employees", employeeRoutes);
app.use("/api/v1/tasks", taskRoutes);

//  Global Error Handler
app.use((err, req, res, next) => {
  console.error(" Server Error:", err);
  res.status(err.statusCode || 500).json({
    message: err.message || "Internal Server Error",
    errors: err.errors || [],
  });
});
console.log(" All registered routes:", 
  app._router.stack
    .filter(r => r.route)
    .map(r => ({
      path: r.route.path,
      methods: Object.keys(r.route.methods)
    }))
);

//  Start Server
const PORT = process.env.PORT || 3002;
app.listen(PORT, () => {
  console.log(` Server running on http://localhost:${PORT}`);
});

注:员工模块的实现方式与任务模块一致,且功能正常。

问题排查与解决方案

核心问题:API版本路径不匹配

错误信息Cannot POST /api/v2/tasks/与server.js代码对比可见,任务路由实际挂载的路径是/api/v1/tasks,但请求的是/api/v2/tasks/,版本号不匹配导致Express无法找到对应的路由处理逻辑。

解决步骤

  1. 修正请求路径:将创建任务的请求地址改为/api/v1/tasks(建议去掉末尾斜杠,保持与路由定义一致,Express虽兼容斜杠结尾,但统一格式可避免潜在问题)。
  2. 若需支持v2版本:在server.js中添加v2版本的路由挂载:
    app.use("/api/v2/tasks", taskRoutes);
    
    这样/api/v2/tasks路径也能正常处理POST请求。

额外验证点

  • 确认task.routes.js中的POST /路由已正确注册(代码中已添加,且注释标注已修复)。
  • 检查请求是否携带合法的JSON格式请求体,且express.json()中间件已在server.js中启用(代码中已配置)。
  • 查看服务器启动日志,确认/api/v1/tasks相关路由已被正确注册(server.js中有打印所有注册路由的代码,可核对输出内容)。

内容的提问来源于stack exchange,提问作者Ahmed Mohamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:07:02