后端中间件无法到达报头,但是邮差工作正常



我正在使用react和react-redux与axios创建新的应用程序(电子商务)。后端使用mongodb (MERN堆栈)。

保存数据到数据库时没有问题,但是当我从数据库中间件获得数据时,无法从标头到达令牌。但是邮差可以很好地获取和保存数据。

我在将数据保存到数据库时使用相同的中间件,它工作得很好。但是当我试图从数据库中获取数据时,我得到未经授权的错误。

这是我的代码。

后端;

服务器文件;

import express from "express";
import connectDB from "./config/db.js";
import dotenv from "dotenv";
import colors from "colors";
import productRoutes from "./routes/productRoutes.js";
import userRouters from "./routes/userRoutes.js";
import shippingAddressRoutes from "./routes/shippingAddressRoutes.js";
import { notFound, errorHandler } from "./middleware/errorMiddleware.js";
dotenv.config();
connectDB();
const app = express();
// body parser
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// API route
app.get("/", (req, res) => {
res.send("API is running....");
});
// route for products
app.use("/api/products", productRoutes);
// route for users
app.use("/api/users", userRouters);
// route for shipping address
app.use("/api/shippingaddress", shippingAddressRoutes);
app.use(notFound);
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold
)
);

shippingAddressRoute文件;

import express from "express";
import {
saveAddress,
changeAddress,
getAddress,
} from "../controllers/shippingAddressController.js";
import protect from "../middleware/authMiddleware.js";
const router = express.Router();
router
.route("/")
.get(protect, getAddress)
.post(protect, saveAddress)
.put(protect, changeAddress);
export default router;

shippingAddressController文件;

import asyncHandler from "express-async-handler";
import ShippingAddress from "../models/shippingAddressModel.js";
import User from "../models/userModel.js";
// @desc   get address
// @route  GET /api/shippingaddress
// @access Private
const getAddress = asyncHandler(async (req, res) => {
const user = User.findById(req.user._id);
if (user) {
const { email } = req.body;
const shippingAddress = await ShippingAddress.findOne({
userEmail: email,
});
if (shippingAddress) {
res.status(200);
res.json({
address: shippingAddress.address,
city: shippingAddress.city,
postalCode: shippingAddress.postalCode,
county: shippingAddress.country,
email: shippingAddress.userEmail,
});
} else {
res.status(404);
throw new Error("Address not found");
}
} else {
res.status(404);
throw new Error("User not found");
}
});
// @desc   save address
// @route  POST /api/shippingaddress
// @access Private
const saveAddress = asyncHandler(async (req, res) => {
const user = User.findById(req.user._id);
if (user) {
const { address, city, postalCode, country, email } = req.body;
const existAddress = await ShippingAddress.findOne({ userEmail: email });
if (existAddress) {
res.status(400);
throw new Error(
"User already has an address. If you want to change address, try CHANGE ADDRESS."
);
} else {
const createdAddress = await ShippingAddress.create({
user: req.user._id,
address,
city,
postalCode,
country,
userEmail: email,
});
if (createdAddress) {
res.status(201);
res.json({
address: createdAddress.address,
city: createdAddress.city,
postalCode: createdAddress.postalCode,
county: createdAddress.country,
email: createdAddress.userEmail,
});
} else {
res.status(400);
throw new Error("Address did not save");
}
}
} else {
res.status(404);
throw new Error("User not found");
}
});
// @desc   change address
// @route  PUT /api/shippingaddress
// @access Private
const changeAddress = asyncHandler(async (req, res) => {
const user = await User.findById(req.user._id);
if (user) {
const { email } = req.body;
const shippingAddress = await ShippingAddress.findOne({
userEmail: email,
});
if (shippingAddress) {
shippingAddress.address = req.body.address || shippingAddress.address;
shippingAddress.city = req.body.city || shippingAddress.city;
shippingAddress.postalCode =
req.body.postalCode || shippingAddress.postalCode;
shippingAddress.country = req.body.country || shippingAddress.country;
const updatedShippingAddress = await shippingAddress.save();
res.status(200);
res.json({
address: updatedShippingAddress.address,
city: updatedShippingAddress.city,
postalCode: updatedShippingAddress.postalCode,
county: updatedShippingAddress.country,
email: updatedShippingAddress.userEmail,
});
} else {
res.status(404);
throw new Error("Address not found");
}
} else {
res.status(404);
throw new Error("User not found");
}
});
export { getAddress, saveAddress, changeAddress };

authMiddleware文件;


import jwt from "jsonwebtoken";
import User from "../models/userModel.js";
import asyncHandler from "express-async-handler";
const protect = asyncHandler(async (req, res, next) => {
let token = req.headers.token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith("Bearer")
) {
try {
// get token from req
token = req.headers.authorization.split(" ")[1];
// verify token
const decode = jwt.verify(token, process.env.JWT_SECRET);
// get user from token
req.user = await User.findById(decode.id).select("-password");
next();
} catch (error) {
res.status(401);
throw new Error("Not1 Authorized");
}
}
if (!token) {
res.status(401);
throw new Error("Not2 Authorized");
}
});
export default protect;

前端;

shippingAction文件;

import { createAsyncThunk } from "@reduxjs/toolkit";
import shippingServices from "./shippingServices";
// get address
export const getAddress = createAsyncThunk(
"shipping/get",
async (userInfo, thunkAPI) => {
try {
return await shippingServices.get(userInfo);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
// save address
export const saveAddress = createAsyncThunk(
"shipping/save",
async (addressInfo, thunkAPI) => {
try {
return await shippingServices.save(addressInfo);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
// update address
export const updateAddress = createAsyncThunk(
"shipping/update",
async (addressInfo, thunkAPI) => {
try {
return await shippingServices.update(addressInfo);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);

shippingServices文件;


import axios from "axios";
const SHIPPING_ADDRESS_URL = "/api/shippingaddress";
// save address
const save = async (addressInfo) => {
const config = {
headers: {
Authorization: `Bearer ${addressInfo.token}`,
},
};
const { data } = await axios.post(SHIPPING_ADDRESS_URL, addressInfo, config);
return data;
};
// get address
const get = async (userInfo) => {
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.get(SHIPPING_ADDRESS_URL, userInfo, config);
return data;
};
// update address
const update = async (addressInfo) => {
const config = {
headers: {
Authorization: `Bearer ${addressInfo.token}`,
},
};
const { data } = await axios.put(SHIPPING_ADDRESS_URL, addressInfo, config);
return data;
};
const shippingServices = {
save,
get,
update,
};
export default shippingServices;

shippigPage文件;

import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Form, Button } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import FormContainer from "../components/FormContainer";
import Message from "../components/Message";
import Loader from "../components/Loader";
import { shippingSliceAction } from "../features/shipping/shippingSlice";
import { saveAddress, getAddress } from "../features/shipping/shippingAction";
function ShippingPage() {
const { user } = useSelector((state) => state.auth);
const { shippingAddress, isLoading, isSuccess, isError, message } =
useSelector((state) => state.shipping);
const [address, setAddress] = useState("");
const [city, setCity] = useState("");
const [postalCode, setPostalCode] = useState("");
const [country, setCountry] = useState("");
const [comMessage, setComMessage] = useState(null);
const dispatch = useDispatch();
const navigate = useNavigate();
useEffect(() => {
if (shippingAddress) {
setAddress(shippingAddress.address);
setCity(shippingAddress.city);
setPostalCode(shippingAddress.postalCode);
setCountry(shippingAddress.country);
} else {
const userInfo = {
token: user.token,
email: user.email,
};
dispatch(getAddress(userInfo));
}
}, []);
const submitHandler = (e) => {
e.preventDefault();
if (!user) {
navigate("/login");
} else {
if (!address || !city || !postalCode || !country) {
setComMessage("Please fill all fields");
setTimeout(() => setComMessage(null), 3000);
} else {
dispatch(
shippingSliceAction.takeAddress({
email: user.email,
address,
city,
postalCode,
country,
})
);
localStorage.setItem(
"userAddress",
JSON.stringify({
email: user.email,
address,
city,
postalCode,
country,
})
);
}
}
};
const saveContinue = () => {
if (!user) {
navigate("/login");
} else {
dispatch(
saveAddress({
email: user.email,
address,
city,
postalCode,
country,
token: user.token,
})
);
if (isSuccess) {
setComMessage("Your Address Saved");
setTimeout(() => dispatch(shippingSliceAction.reset()), 3000);
setTimeout(() => setComMessage(null), 3000);
setTimeout(() => navigate("/payment"), 4000);
}
}
};
return (
<FormContainer>
<h1>Shipping</h1>
{comMessage && <Message variant="danger">{comMessage}</Message>}
<Form onSubmit={submitHandler}>
<Form.Group controlId="address">
<Form.Label>Address</Form.Label>
<Form.Control
type="text"
placeholder="Enter Address"
value={address}
onChange={(e) => setAddress(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="city">
<Form.Label>City</Form.Label>
<Form.Control
type="text"
placeholder="Enter City"
value={city}
onChange={(e) => setCity(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="postalCode">
<Form.Label>Postal Code</Form.Label>
<Form.Control
type="number"
placeholder="Enter Postal Code"
value={postalCode}
onChange={(e) => setPostalCode(e.target.value)}
></Form.Control>
</Form.Group>
<Form.Group controlId="country">
<Form.Label>Country</Form.Label>
<Form.Control
type="text"
placeholder="Enter Country"
value={country}
onChange={(e) => setCountry(e.target.value)}
></Form.Control>
</Form.Group>
<Button className="shippingButton" type="submit" variant="primary">
Continue without saving
</Button>
{isLoading && <Loader />}
{isSuccess && <Message variant="success"></Message>}
{isError && <Message variant="danger">{message}</Message>}
<Button
className="shippingButton save"
type="button"
variant="secondary"
onClick={saveContinue}
>
Save my address and continue
</Button>
</Form>
</FormContainer>
);
}
export default ShippingPage;

// shippingServices.js
const { data } = await axios.get(SHIPPING_ADDRESS_URL, userInfo, config);

应该是

const { data } = await axios.get(SHIPPING_ADDRESS_URL, config);

也停止使用不必要的软件包,如express-async-handler,只需用try/catch块覆盖整个中间件功能体,在catch块中调用next(error);它会工作得很好。