【发布时间】:2021-04-27 23:13:43
【问题描述】:
我有一个位于 main-domain.tld/api/ 的 ngnix 上托管的 Express API 和一个位于 sub.main-domain.tld 的管理面板,用于向我的 API 发送请求。
当我尝试从我的管理面板向我的 API 发送请求时,我收到一个 CORS 错误,70% 的时间与我请求的路由和使用的方法(POST、GET 等)无关。
我无法理解 2 件事:
- 首先是我收到 CORS 错误的原因,因为我启用了所有 源自我的 API 源代码。
- 第二个是为什么我只收到 70% 的 CORS 错误 当我的管理面板发出请求时,如果我的 API 设置错误,这不应该发生,对吧?
我整天都在寻找解决方案并尝试以各种可能的方式创建corsOptions,但我仍然遇到同样的问题,不管我做什么。
CORS 错误:
API 源代码:
import cors from 'cors';
import express from 'express';
import jwt from 'jsonwebtoken';
import { generateToken, getCleanUser } from './utils';
import { Admins, Utenti, Prodotti, Acquisti } from './models';
require('dotenv').config();
const app = express();
const port = process.env.PORT;
const mongoose = require('mongoose');
mongoose.connect('mongodb://domain', {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
}).then(db => console.log('Il DB è connesso!'))
.catch(err => console.log(err));
// CORS
app.use(cors());
// parse application/json
app.use(express.json());
// parse application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
// Middleware that checks if JWT token exists and verifies it if it does exist.
// In all future routes, this helps to know if the request is authenticated or not.
app.use((req, res, next) => {
// check header or url parameters or post parameters for token
let token = req.headers['authorization'];
if (!token) return next(); //if no token, continue
token = token.replace('Bearer ', '');
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(401).json({
error: true,
message: "Invalid user."
});
} else {
req.user = user; //set the user to req so other routes can use it
next();
}
});
});
// request handlers
app.get('/api', (req, res) => {
if (!req.user) return res.status(401).json({ success: false, message: 'Invalid user to access it.' });
res.send('Welcome! - ' + req.user.username);
});
//*================================
//* ADMINS SIGNIN
//*================================
app.post('/api/admins/signin', async (req, res) => {
try {
const user = req.body.username;
const pwd = req.body.password;
// return 400 status if username/password is not exist
if (!user || !pwd) {
return res.status(401).json({
error: true,
message: "Username or Password required!"
});
}
await Admins.findOne({ 'username': user, 'password': pwd }, (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
// return 401 status if the credential is not match.
if (!data) {
return res.status(401).json({
error: true,
message: "Username or Password is Wrong!"
});
}
// generate token
const token = generateToken(data);
// get basic user details
const userObj = getCleanUser(data);
// return the token along with user details
return res.json({ user: userObj, token });
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DI ADMIN SIGNIN >> ${error}`);
return res.status(400);
}
});
//*================================
//* USERS SIGNIN
//*================================
app.post('/api/users/signin', async (req, res) => {
try {
const user = req.body.username;
const pwd = req.body.password;
// return 400 status if username/password is not exist
if (!user || !pwd) {
return res.status(401).json({
error: true,
message: "Username or Password required!"
});
}
await Utenti.findOne({ 'username': user, 'password': pwd }, (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
// return 401 status if the credential is not match.
if (!data) {
return res.status(401).json({
error: true,
message: "Username or Password is Wrong!"
});
}
// generate token
const token = generateToken(data);
// get basic user details
const userObj = getCleanUser(data);
// return the token along with user details
return res.json({ user: userObj, token });
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DI USERS SIGNIN >> ${error}`);
return res.status(400);
}
});
//*================================
//* USERS SIGNUP
//*================================
app.post('/api/users/signup', async (req, res) => {
try {
// return 400 status if username/password is not exist
if (!req.body.username || !req.body.password || !req.body.email) {
return res.status(400).json({
error: true,
message: "Every field in the form is required!"
});
}
await Utenti.findOne({ 'username': req.body.username }, async (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
if (data) {
return res.status(400).json({
error: true,
message: "Username already taken!"
});
}
await Utenti.find().sort({ _id: -1 }).exec(async (err, lastUserSignedUp) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
let newUser;
if (lastUserSignedUp[0]) {
newUser = new Utenti({
id: (lastUserSignedUp[0].id + 1),
username: req.body.username,
password: req.body.password,
email: req.body.email
});
} else {
newUser = new Utenti({
id: 0,
username: req.body.username,
password: req.body.password,
email: req.body.email
});
}
await newUser.save();
return res.json(newUser);
});
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DI USERS SIGNUP >> ${error}`);
return res.status(401)
}
});
//*================================
//* ADMINS VERIFY THE TOKEN
//*================================
app.get('/api/verifyAdminToken', (req, res) => {
// check header or url parameters or post parameters for token
const token = req.body.token || req.query.token;
if (!token) {
return res.status(400).json({
error: true,
message: "Token is required."
});
}
// check token that was passed by decoding token using secret
jwt.verify(token, process.env.JWT_SECRET, async (err, user) => {
try {
if (err) return res.status(401).json({
error: true,
message: "Invalid token."
});
await Admins.findOne({ 'username': user.username, 'password': user.password }, (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
// return 401 status if the userId does not match.
if (user._id !== data._id.toString()) {
return res.status(401).json({
error: true,
message: "Invalid user."
});
}
// get basic user details
const userObj = getCleanUser(data);
return res.json({ user: userObj, token });
});
} catch (error) {
console.log(`ERRORE NELLA GET REQUEST DI VERIFY-TOKEN >> ${error}`);
}
});
});
//*================================
//* USERS VERIFY THE TOKEN
//*================================
app.get('/api/verifyToken', (req, res) => {
// check header or url parameters or post parameters for token
const token = req.body.token || req.query.token;
if (!token) {
return res.status(400).json({
error: true,
message: "Token is required."
});
}
// check token that was passed by decoding token using secret
jwt.verify(token, process.env.JWT_SECRET, async (err, user) => {
try {
if (err) return res.status(401).json({
error: true,
message: "Invalid token."
});
await Utenti.findOne({ 'username': user.username, 'password': user.password }, (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
// return 401 status if the userId does not match.
if (user._id !== data._id.toString()) {
return res.status(401).json({
error: true,
message: "Invalid user."
});
}
// get basic user details
const userObj = getCleanUser(data);
return res.json({ user: userObj, token });
});
} catch (error) {
console.log(`ERRORE NELLA GET REQUEST DI VERIFY-TOKEN >> ${error}`);
}
});
});
//*================================
//* PRODOTTI
//*================================
app.route('/api/prodotti')
.get(async (req, res) => {
try {
if (req.query.categoria !== undefined) {
if (req.query.categoria === 'all') {
await Prodotti.find().exec((err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
})
} else {
await Prodotti.find({ 'categoria': req.query.categoria }, (err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
})
}
} else {
if (!req.query.id) {
await Prodotti.findOne({ 'nome': req.query.nome }, (err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
if (req.query.desc === 'true' && data) {
return res.json(data.desc);
} else {
return res.json(data);
}
});
} else {
await Prodotti.findOne({ 'id': req.query.id }, (err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
});
}
}
} catch (error) {
console.log(`ERRORE NELLA GET REQUEST DEI PRODOTTI >> ${error}`);
}
})
.post(async (req, res) => {
if (req.user) {
try {
await Admins.findOne({ 'username': req.user.username, 'password': req.user.password }, async (err, data) => {
if (err) {
console.error('DB ERROR => ', err);
}
// return 401 status if the credential is not match.
if (!data) {
return res.status(401).json({
error: true,
message: "Access Denied"
});
}
await Prodotti.find().sort({ _id: -1 }).exec(async (err, lastProdottoAggiunto) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
let nuovoProdotto;
if (lastProdottoAggiunto[0]) {
nuovoProdotto = new Prodotti({
id: (lastProdottoAggiunto[0].id + 1),
nome: req.body.nome,
categoria: req.body.categoria,
prezzo: req.body.prezzo,
id_api: req.body.id_api,
desc: req.body.desc
});
} else {
nuovoProdotto = new Prodotti({
id: 0,
nome: req.body.nome,
categoria: req.body.categoria,
prezzo: req.body.prezzo,
id_api: req.body.id_api,
desc: req.body.desc
});
}
await nuovoProdotto.save();
return res.json(nuovoProdotto);
});
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DEI PRODOTTI >> ${error}`);
}
return res.status(403).json({
error: true,
message: 'Access Denied'
});
}
})
.delete(async (req, res) => {
try {
await Prodotti.findOneAndDelete({ 'id': req.body.id }, (err, removed) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json({ success: 'true' });
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DEI PRODOTTI >> ${error}`);
}
});
//*================================
//* ACQUISTI
//*================================
app.route('/api/acquisti')
.get(async (req, res) => {
try {
if (!req.query.id) {
await Acquisti.find({ 'id': req.query.id }, (err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
});
}
} catch (error) {
console.log(`ERRORE NELLA GET REQUEST DEGLI ACQUISTI >> ${error}`);
}
})
.post(async (req, res) => {
if (req.user) {
try {
const nuovoAcquisto = new Acquisti({
id: orderId,
id: req.body.id,
categoria: req.body.categoria,
nome: req.body.nome,
link: req.body.link,
qty: req.body.qty,
spesa: req.body.spesa
});
await nuovoAcquisto.save();
return res.json(nuovoAcquisto);
} catch (error) {
return res.status(401).json({
error: true,
message: `ERRORE NELLA POST REQUEST DEGLI ACQUISTI >> ${error}`
});
}
} else {
return res.status(403).json({
error: true,
message: 'Access Denied'
});
}
});
//*================================
//* UTENTI
//*================================
app.route('/api/utenti')
.get(async (req, res) => {
if (req.user) {
try {
if (req.query.id) {
await Utenti.findOne({ 'id': req.query.id }, (err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
});
} else {
await Utenti.find().exec((err, data) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json(data);
})
}
} catch (error) {
console.log(`ERRORE NELLA GET REQUEST DEGLI UTENTI >> ${error}`);
}
} else {
return res.status(403).send(`
<div style="text-align: center; font-family: 'Trebuchet MS', sans-serif;">
</div>
`);
}
})
.delete(async (req, res) => {
try {
await Utenti.findOneAndDelete({ 'id': req.body.id }, (err, removed) => {
if (err) return res.status(401).json({
error: true,
message: 'DB Problem... '
});
return res.json({ success: 'true' });
});
} catch (error) {
console.log(`ERRORE NELLA POST REQUEST DEI PRODOTTI >> ${error}`);
}
});
app.listen(port, () => {
console.log('Porta API: ' + port);
});
【问题讨论】:
-
与您的问题无关,此结构错误
await Admins.findOne({ 'username': user, 'password': pwd }, (err, data) => { ...});您不使用await并将回调传递给您的数据库。选择一个或另一个。如果您传递回调,则请求不会返回承诺,因此await毫无意义(什么都不做)。如果您不传递回调,那么它将返回一个承诺,您实际上可以从await中获取结果。
标签: javascript node.js express http-headers cors