使用Axios请求服务器遇404错误,动态路由下/api/dashboard无法访问
动态路由下Axios请求/api/dashboard返回404的问题
我尝试为每个用户创建动态路由localhost:3000/{dynamicId}/userPage,但在UserPage组件中使用Axios发送GET请求到api/dashboard时返回404错误。服务器端已定义/dashboard路由,且通过UUID生成的dynamicId已作为动态路由参数配置,疑惑为何提示该路由不存在。
相关代码
App.jsx
import { useState } from 'react' import reactLogo from './assets/react.svg' import './App.css' import LoginPage from "./pages/LoginPage" import { BrowserRouter, Routes, Route } from "react-router-dom"; import HomePage from './pages/HomePage'; import SignUpPage from './pages/SignUpPage' import UserPage from './pages/UserPage'; function App() { return ( <> <BrowserRouter> <Routes> <Route exact path="/" element={<HomePage/>}/> <Route path="login" element={<LoginPage/>}/> <Route path="signup" element={<SignUpPage/>}/> <Route path=":user/userpage" element={<UserPage />} /> </Routes> </BrowserRouter> </> ) } export default App
UserPage.jsx
import axios from "axios" import Button from "../Shared/FormElement/Button" import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; function UserPage(props) { const[isLoading,setIsLoading]=useState(false) const[isLoggedin, setIsLoggedin]=useState(false) const handleLoad=(event)=>{ setIsLoading(true) axios({ method: "get", url: "api/dashboard", }) .then((response) => { console.log("UserLoggedin:",response.data) setIsLoading(false) setIsLoggedin(true) if (!response.data) { navigate("/login") } }) } const navigate = useNavigate(); useEffect(() => { console.log("being called") handleLoad() }, []); function handleclick(event){ axios({ method: "post", url: "api/logout" }).then((response) => { console.log(response.data) if (!response.data) navigate("/login") }) } return isLoggedin&&<div> <h1>Hello User</h1> <Button type="submit" style="primary" onClick={handleclick}> Logout</Button> {isLoading &&<h2>Loading...</h2>} </div> } export default UserPage
vite.config.js
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], server: { proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } })
服务器端代码
require('dotenv').config() const { v4: uuidv4 } = require('uuid'); const bodyParser = require("body-parser") const express = require("express") const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const GoogleStrategy = require('passport-google-oauth20').Strategy; const app = express() const mongoose = require('mongoose'); const cors = require('cors'); const bcrypt = require('bcrypt'); const session = require('express-session'); const saltRounds = 10; app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()); app.use(cors()) PORT = process.env.PORT || 3000 app.use(session({ secret: process.env.SECRET, resave: false, saveUninitialized: true, })) app.use(passport.initialize()) app.use(passport.session()) const authUser = (email, password, done) => { Account.findOne({ Email: email }).exec() .then((account) => { if (account) { bcrypt.compare(password, account.Password).then(function (result) { if (result) { done(null, { account }, { message: "Succesfull" }) } else { done(null, false, { message: "Invalid password" }) } }) } else { done(null, false, { message: "Invalid password" }) } }) .catch((error) => done(error)); } passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' },authUser)) passport.serializeUser((userObj, done) => { done(null, userObj.account.id); }); passport.deserializeUser((userId, done) => { Account.findOne({ id: userId }) .exec() .then((account) => { done(null, { account }); }) .catch((error) => done(error)); }); const { Schema, model } = mongoose; const MongooseConnect = async () => { try { const conn = await mongoose.connect(process.env.MONGODBBKEY); console.log(`MongoDB Connected: ${conn.connection.host}`) } catch (error) { console.log(error) process.exit(1) } } const user_accounts = new Schema({ id:String, first_name: String, last_name: String, Email: String, Password: String }) const Account = model("Account", user_accounts) app.post("/login", (req, res, next) => { passport.authenticate("local", (err, user, info) => { if (user) { req.logIn(user, (err) => { if (err) { return next(err); } console.log(user, info); console.log(req.isAuthenticated()); console.log(user.account.id); return res.json({ id: user.account.id, authentication: true, }); }); } else { console.log(user, info); return res.json({ id: user.account.id, authentication: false, }); } })(req, res, next); }); app.get("/dashboard",(req,res,next)=>{ console.log(req.isAuthenticated()) res.json(req.isAuthenticated()) }) app.post('/logout', function(req, res, next){ req.logout(function(err) { if (err) { return next(err); } console.log(req.isAuthenticated()) res.json(req.isAuthenticated()) }); }); app.post("/signup", async (req, res, next) => { Account.findOne({ Email: req.body.Email }).exec() .then((account) => { if (!account) { bcrypt.hash(req.body.password, saltRounds).then(function (hash) { const user = Account({ id:uuidv4(), first_name: req.body.first_name, last_name: req.body.lastname, Email: req.body.Email, Password: hash, }) user.save() }); console.log("User Created"); const Accountexist = false res.json(Accountexist) } else { console.log("Account Exist") const Accountexist = true res.json(Accountexist) } }) }) MongooseConnect().then( app.listen(PORT, () => { console.log(`Working in port ${PORT}`) }) )
错误截图

问题原因与解决方案
1. 核心问题:相对路径解析错误
你在UserPage里写的请求URL是"api/dashboard",这是相对路径。当页面处于localhost:3000/abc123/userpage这种多层路由下时,浏览器会把请求路径拼接成localhost:3000/abc123/api/dashboard——这显然不是后端定义的/dashboard路由,所以返回404。
解决办法:给所有API请求的URL加上开头的斜杠,改成绝对路径:
// 修改dashboard请求 axios({ method: "get", url: "/api/dashboard", // 注意开头的/ }) // 修改logout请求 axios({ method: "post", url: "/api/logout" // 同样加/ })
2. 额外排查点:端口与代理配置
你的Vite代理配置是对的,把/api开头的请求转发到后端3000端口,但要确保:
- 后端确实运行在3000端口,Vite开发服务器运行在其他端口(比如默认的5173),避免端口冲突
- 代理的
rewrite规则正确:path.replace(/^\/api/, '')会把/api/dashboard转成/dashboard,和后端路由匹配
3. 潜在问题:会话凭证传递
如果后续请求/dashboard返回未授权,需要确保会话Cookie能正确传递:
- 前端Axios请求加上
withCredentials: true - 后端CORS配置指定允许的Origin并开启凭证支持
修改示例:
// 前端请求添加凭证 axios({ method: "get", url: "/api/dashboard", withCredentials: true }) // 后端修改CORS配置 app.use(cors({ origin: "http://localhost:5173", // Vite服务器地址 credentials: true }))
内容的提问来源于stack exchange,提问作者roblov Cave
相关产品推荐
相关产品推荐

