这是我的第一个问题,但我完全诺奥知道该怎么做:/我学习javascript技术。我写了我的MERN应用程序,我在那里处理登录和注册功能。我的后端部署在heroku上,但客户端部署在netlify上。一切都在本地运行正常,但当我在部署到heroku和netlify后测试我的应用程序时,一切都正常,直到我尝试向后端发送请求(例如在登录过程中)。我的请求大约等待20-30秒,在这段时间后,我会收到以下内容的通知-“***访问XMLHttpRequest at ' https://pokemontrainer-app.herokuapp.com/auth/signin' from origin ' https:pokemon-trainer-mern-app.netlify.app'已被CORS策略阻止:请求的资源上没有“Access-Control-Allow-Origin”头。***"。我一直在寻找解决方案。我经常看到netlify的客户端构建文件夹的infos about _redirects文件。不幸的是,当涉及到这个问题时,文档非常简短且不清楚。也许你们中的某个人遇到了类似的问题并成功解决了它?如果_redirects文件确实是解决方案,我能简单地问一下我该如何准备吗?
这是我后端代码:
server.js文件:
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser')
const mainRoutes = require('./routes/main.js');
const signinSignupRoutes = require('./routes/signInSignUp.js');
const userTrainersRoutes = require('./routes/userTrainers.js');
require('dotenv').config({ path: './.env' });
const app = express();
const port = process.env.PORT || 8000;
console.log(process.env.FRONTEND_URI);
//------Express-------
app.use(bodyParser.json({limit: '500mb'}));
app.use(bodyParser.urlencoded({limit: '500mb', extended: true}));
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded());
app.use(cors(
{
credentials: true,
origin: 'https://pokemon-trainer-mern-app.netlify.app'
})
);
app.use('/', mainRoutes);
app.use('/auth', signinSignupRoutes);
app.use('/loggedUser', userTrainersRoutes);
//------Mongoose-------
const main = async() => {
try {
await mongoose.connect(`mongodb+srv://${process.env.USERS_USERNAME}:${process.env.USERS_API_KEY}@pokemon-app.2s1cy.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`);
console.log('Database connection works!')
}catch(err) {
console.log(err.message);
}
}
main()
.then(()=> app.listen(port, () => {
console.log(`Server works on port ${port}`);
}))
.catch(err => console.log(err.message));
登录.js文件(& U):
const bcrypt = require('bcryptjs');
const Joi = require('joi');
const jwt = require('jsonwebtoken');
const {User, validation} = require('../models/user.js');
const getUsers = async (req, res) => {
try {
const users = await User.find();
res.status(200).json(users);
} catch(err) {
res.status(404).json(err.message);
}
}
const signUp = async(req, res) => {
try{
const {error} = validation(req.body);
error && res.status(400).send({message: error.details[0].message});
const user = await User.findOne({email: req.body.email});
if(user) {
res.status(409).send({message: 'User with this email already exists.'})
} else {
if(req.body.userName === "") {
res.status(400).send({message: `Username field is empty`});
} else if(req.body.password !== req.body.confirmPassword || req.body.password === "") {
res.status(400).send({message: `Passwords aren't the same or password field is empty`});
} else {
const hashedPassword = await bcrypt.hash(req.body.password, 12);
await User.create({email: req.body.email, userName: req.body.userName, password: hashedPassword});
res.status(201).send({message: 'User registered succesfully!'});
}
}
} catch(err) {
res.status(500).send({message: 'Internal server error :('});
}
}
const signIn = async(req, res) => {
res.setHeader('Access-Control-Allow-Origin', 'https://pokemon-trainer-mern-app.netlify.app');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
try{
const {error} = signInValidation(req.body);
error && res.status(400).send({message: error.details[0].message});
const user = await User.findOne({email: req.body.email});
!user && res.status(401).send({message: 'User with this email adress is not registered :('});
const validatedPassword = await bcrypt.compare(req.body.password, user.password);
!validatedPassword && res.status(401).send({message: 'Incorrect password :('});
const token = await user.generateAuthToken(user._id, user.email);
res.cookie('token', token, {
maxAge: 7 * 24 * 60 * 60 * 1000,
httpOnly: process.env.NODE_ENV === 'production' ? true : false,
secure: false,
}).status(200).send({message: 'Log in succesfully', userData: {userId:user._id, userName: user.userName, email: user.email, trainers: user.trainers, logged: true}});
} catch(err) {
console.log(err.message);
}
}
const signInViaGoogle = async(req, res) => {
try{
const user = await User.findOne({email: req.body.email});
!user && res.status(401).send({message:'You have to register your account with this email in this app'});
const token = user.generateAuthToken(user._id, user.email);
res.cookie('token', token, {
maxAge: 7 * 24 * 60 * 60 * 1000,
httpOnly: process.env.NODE_ENV === `${production}` ? true : false,
secure: false,
}).status(200).send({message: 'Log in succesfully', userData: {userId:user._id, userName: user.userName,email: user.email, trainers: user.trainers, logged: true}});
} catch(err) {
res.status(500).send({message: 'Internal server error :('});
}
}
const logout = async(req, res) => {
try {
const {token} = req.cookies;
token && res.clearCookie('token').send({message: 'Cookie cleared'});
} catch(err) {
res.status(500).send({message: 'Internal server error :('});
}
}
const newSession = async(req, res) => {
const {token} = req.cookies;
!token ? res.status(200).send({cookie: false, logged: false}) : res.status(200).send({cookie: true, logged: true});
}
// validation for signIn
const signInValidation = (data) => {
const JoiSchema = Joi.object({
email: Joi.string().required().label('E-mail'),
password: Joi.string().required().label('Password'),
});
return JoiSchema.validate(data);
}
module.exports = {getUsers, signUp, signIn, signInViaGoogle, logout, newSession}
客户端代码:
apiHandling.js文件:
import axios from 'axios';
import { loginNativeUser, updateUserData, newSession } from '../actions/userActions.js'
const url = 'https://pokemontrainer-app.herokuapp.com';
const instance = axios.create({
baseUrl: url,
withCredentials: true,
credentials: 'include',
})
export const newSess = async (dispatch) => {
await instance.get(`${url}/auth/newSession`)
.then(res => {
dispatch(newSession(res.data));
})
.catch(err => console.log(err.message));
}
export const signInByGoogle = async (userData, setError, history, dispatch) => {
await instance.post(`${url}/auth/signin/google`, {
email: userData.email,
})
.then(res => {
setError(null);
dispatch(loginNativeUser(res.data.userData));
history.push('/');
})
.catch(err => {
setError(err.response.data.message);
history.push('/auth/signin');
alert(err.response.data.message);
})
}
export const signIn = async (formData, setError, history, dispatch) => {
await instance.post(`${url}/auth/signin`, {
password: formData.password,
email: formData.email,
})
.then(res => {
setError(null);
dispatch(loginNativeUser(res.data.userData));
history.push('/');
})
.catch(err => {
setError(err.response.data.message);
history.push('/auth/signin');
alert(err.response.data.message);
});
}
export const signUp = async (formData, setError, history) => {
await instance.post(`${url}/auth/signup`, {
userName: formData.userName,
password: formData.password,
confirmPassword: formData.confirmPassword,
email: formData.email,
})
.then(res => {
setError(null);
history.push('/');
alert('Registered succesfully')
})
.catch(err => {
setError(err.response.data.message);
history.push('/auth/signup');
alert(err.response.data.message);
});
}
export const cookieClear = async () => {
await instance.get(`${url}/auth/deleteCookie`)
.then(res => {
console.log('Cookie cleared');
})
.catch(err => {
console.log(err.response.data.message);
});
}
export const addTrainer = async (userId, trainer) => {
await instance.patch(`${url}/loggedUser/${userId}/addTrainer`, {
userId: userId,
trainer: trainer
})
.then(res => {
alert('Trainer added');
})
.catch(err => {
alert(err.response.data.message);
});
}
export const removeTrainer = async (userId, trainerId) => {
await instance.patch(`${url}/loggedUser/${userId}/${trainerId}/removeTrainer`, {
userId: userId,
trainerId: trainerId
})
.then(res => {
alert(res.data.message);
})
.catch(err =>{
alert(err.response.data.message);
})
}
export const addPokemon = async(userId, trainerId, pokemon) => {
await instance.patch(`${url}/loggedUser/${userId}/${trainerId}/${pokemon}/addPokemon`, {
userId: userId,
trainerId: trainerId,
pokemon: pokemon
})
.then(res => {
alert('Pokemon caught');
})
.catch((err) => {
alert(err.response.data.message);
})
}
export const updateData = async (userId, dispatch) => {
await instance.post(`${url}/loggedUser/${userId}/updateData`, {
userId: userId,
})
.then(res => {
dispatch(updateUserData(res.data.userData));
})
.catch(err => {
console.log(err.response.data.message);
});
}
如果需要的话,我也可以发送一个带有代码的github链接。
提前感谢您的回答。
2条答案
按热度按时间woobm2wo1#
你可以添加一个中间件到你的express应用程序。我碰巧写了一些cors配置我的express api今天。供您参考(服务器端代码):
然后在您的应用中使用此中间件:
有关CORS的更多信息,请参阅以下官方介绍:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
acruukt92#
谢谢大家的回复。我决定把我的整个应用程序放在heroku上。它工作正常。CORS策略问题消失了。问题与不同的域有关(heroku用于后端,netlify用于前端)。我决定使用这个解决方案,因为我从来没有尝试过把前端放在heroku上。它需要重新安排我的项目文件夹。现在我的项目结构是:
enter image description here
1.请访问Heroku.com
1.单击您的“控制面板”
1.单击“新建”
1.点击“创建新应用程序”
1.在server.js文件中添加:
1.在客户端package.json文件中添加“代理”:
1.在heroku应用程序中设置环境变量:
转到“设置”,单击“显示配置变量”添加一个新变量,然后单击“添加”。
1.在根文件夹的package.json中添加下一个脚本:
1.在Procfile文件夹中:
1.在根文件夹中heroku git:remote -a应用程序名称-from-heroku git init git add . git commit -m“提交名称”git push heroku主文件夹(或主文件夹)
我在www.example.com找到了这个清晰的解决方案coursework.vschool.io(文章标题-部署MERN应用程序到Heroku(使用Git Master分支和MongoDBMap集)。