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

React前端向Node.js后端发POST请求遇404错误求助

404错误排查:React前端POST请求无法抵达Node.js后端

问题背景

使用React前端 + Node.js后端开发应用,添加交易时发送POST请求出现Error: Request failed with status code 404,请求无法到达后端。


前端相关代码

触发请求的组件代码

<div className='transaction-new-trade-container input-container-style-dash'>
   <h2>Add new trade</h2>
   <label>Stock symbol</label>
   <input
      type='text'
      value={newTrade.symbol}
      name='symbol'
      onChange={handleInputChange}
   />

   <label>Shares amount</label>
   <input
      type='number'
      value={newTrade.amount === 0 ? '' : newTrade.amount}
      name='amount'
      onChange={handleInputChange}
   />

   <label>Entry price</label>
   <input
      type='number'
      value={newTrade.entryPrice === 0 ? '' : newTrade.entryPrice}
      name='entryPrice'
      onChange={handleInputChange}
   />

   <label>Exit price</label>
   <input
      type='number'
      value={newTrade.exitPrice === 0 ? '' : newTrade.exitPrice}
      name='exitPrice'
      onChange={handleInputChange}
   />
   <button
      className='btn-style-3'
      onClick={() => onAddingNewTrade(newTrade)}
   >
      Add new trade
   </button>
</div>

onAddingNewTrade函数

function onAddingNewTrade(newTrade) {
      newTrade.day = utilService.getDate()
      newTrade.pl = tradeService.calculatePL(
         newTrade.symbol,
         newTrade.amount,
         newTrade.entryPrice,
         newTrade.exitPrice
      )
      newTrade.percentage = tradeService.calculatePercentageChange(
         newTrade.entryPrice,
         newTrade.exitPrice
      )
      newTrade.timestamp = Date.now()
      addTrade(newTrade)
   } 

addTrade函数

export async function addTrade(trade) {
   try {
      const savedTrade = await tradeService.save(trade)
      console.log('Added Trade', savedTrade)
      store.dispatch(getActionAddTrade(savedTrade))
      return savedTrade // maybe no need for it - consider removing later
   } catch (err) {
      console.log('Cannot add trade', err)
      throw err
   }
}

发送POST请求的save函数

async function save(trade) {
   var savedTrade
   if (trade._id) {
      savedTrade = await httpService.put(`trade/${trade._id}`, trade) // if trade has Id so update
   } else {
      console.log('sending request to backend', trade)
      savedTrade = await httpService.post('/trade', trade) // if trade does not has id create add new trade
   }
   return savedTrade
}

后端相关代码

服务器路由挂载

app.use('/api/trade', tradeRoutes)

交易路由文件

import express from 'express'
import { requireAuth } from '../../middlewares/requireAuth.middleware.mjs'
import { log } from '../../middlewares/logger.middleware.mjs'
import { getTrades, getTradeById, addTrade, updateTrade, removeTrade, addTradeMsg, removeTradeMsg } from './trade.controller.mjs'

const router = express.Router()

// We can add a middleware for the entire router:
// router.use(requireAuth)

router.get('/', log, getTrades)
router.get('/:id', getTradeById)
router.post('/trade',requireAuth, addTrade) // add new trade
router.put('/:id', requireAuth, updateTrade) // update existing trade
router.delete('/:id', requireAuth, removeTrade)
// router.delete('/:id', requireAuth, requireAdmin, removeTrade)

router.post('/:id/msg', requireAuth, addTradeMsg)
router.delete('/:id/msg/:msgId', requireAuth, removeTradeMsg)

export const tradeRoutes = router

addTrade控制器函数

export async function addTrade(req, res) {
  const {loggedinUser} = req
  console.log('from front', req.body)
  try {
    const trade = req.body
    trade.owner = loggedinUser
    const addedTrade = await tradeService.add(trade)
    res.json(addedTrade)
  } catch (err) {
    logger.error('Failed to add trade', err)
    res.status(400).send({ err: 'Failed to add trade' })
  }
}

错误原因及解决方法

核心问题:请求路径不匹配

后端实际暴露的POST接口完整路径是/api/trade/trade,但前端请求的路径是/trade,两者完全不匹配,导致404错误。

具体逻辑拆解:

  1. 后端服务器给tradeRoutes挂载了前缀/api/trade:app.use('/api/trade', tradeRoutes)
  2. 交易路由文件中,POST路由定义为router.post('/trade', ...),因此完整接口路径是/api/trade/trade
  3. 前端save函数中,POST请求路径仅为/trade,既缺少/api前缀,也未匹配后端的完整路径结构

修复方案

方案一:直接调整前端请求路径

将前端save函数中的POST请求路径改为后端完整接口路径:

async function save(trade) {
   var savedTrade
   if (trade._id) {
      savedTrade = await httpService.put(`/api/trade/${trade._id}`, trade)
   } else {
      console.log('sending request to backend', trade)
      savedTrade = await httpService.post('/api/trade/trade', trade)
   }
   return savedTrade
}

方案二:优化后端路由结构(更符合RESTful规范)

/api/trade已经代表交易资源集合,POST请求直接用根路径即可,修改交易路由文件中的POST路由:

// 替换原有的 router.post('/trade',requireAuth, addTrade)
router.post('/',requireAuth, addTrade)

此时完整接口路径变为/api/trade,前端同步调整请求路径:

async function save(trade) {
   var savedTrade
   if (trade._id) {
      savedTrade = await httpService.put(`/api/trade/${trade._id}`, trade)
   } else {
      console.log('sending request to backend', trade)
      savedTrade = await httpService.post('/api/trade', trade)
   }
   return savedTrade
}

额外检查项

  • 确认开发环境下前端是否配置了代理,确保/api前缀能正确转发到后端服务器
  • 检查后端服务器是否正常启动,端口与前端代理配置一致
  • 若仍有问题,可临时注释requireAuth中间件,排除权限拦截导致的路径匹配问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 23:30:55