加载资源失败:服务器响应状态为 405(不允许)需要有关 nginx.conf 的帮助
Posted
技术标签:
【中文标题】加载资源失败:服务器响应状态为 405(不允许)需要有关 nginx.conf 的帮助【英文标题】:Failed to load resource: the server responded with a status of 405 (Not Allowed) needs help on nginx.conf 【发布时间】:2019-06-01 18:57:06 【问题描述】:我有完整的带有 AXios 的 MERN 堆栈应用程序。在我的本地主机上,应用程序运行良好,但是当我在 nginx 上部署应用程序时,所有 POST request 都被拒绝。我尝试了许多在网上找到的解决方案,但都不起作用。我认为这是 CORS 问题/ nginx 配置问题。我做的 Nginx.conf 对吗?我的节点在 localhost:8000 上运行,React 在 localhost:3000 上运行。
编辑
我尝试过的事情:
Nginx.conf:
server
listen 80;
server_name lovechangingtheworld.org;
location /
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
节点上也需要这个吗?
router.use((request, response, next) =>
response.header("Access-Control-Allow-Origin", "*");
response.header(
"Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS"
);
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
);
节点:
const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const keys = require("../../config/keys");
const passport = require("passport");
// Load Input Validation
const validateRegisterInput = require("../../validation/register");
const validateLoginInput = require("../../validation/login");
// Load User model
const User = require("../../models/User");
router.use((request, response, next) =>
response.header("Access-Control-Allow-Origin", "*");
response.header(
"Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS"
);
response.header("Access-Control-Allow-Headers", "Content-Type");
next();
);
// @route GET api/users/test
// @desc Tests users route
// @access Public
router.get("/test", (req, res) => res.json( msg: "Users Works" ));
// @route POST api/users/register
// @desc Register user
// @access Public
router.post("/register", (req, res) =>
console.log("333333333333333333333333", req.body);
const errors, isValid = validateRegisterInput(req.body);
// Check Validation
if (!isValid)
return res.status(400).json(errors);
User.findOne( email: req.body.email ).then(user =>
if (user)
errors.email = "Email already exists";
return res.status(400).json(errors);
else
// const avatar = gravatar.url(req.body.email,
// s: '200', // Size
// r: 'pg', // Rating
// d: 'mm' // Default
// );
const newUser = new User(
name: req.body.name,
email: req.body.email,
password: req.body.password
);
bcrypt.genSalt(10, (err, salt) =>
bcrypt.hash(newUser.password, salt, (err, hash) =>
if (err) throw err;
newUser.password = hash;
newUser
.save()
.then(user => res.json(user))
.catch(err => console.log(err));
);
);
);
);
// @route GET api/users/login
// @desc Login User / Returning JWT Token
// @access Public
router.post("/login", (req, res) =>
const errors, isValid = validateLoginInput(req.body);
// Check Validation
if (!isValid)
return res.status(400).json(errors);
const email = req.body.email;
const password = req.body.password;
// Find user by email
User.findOne( email ).then(user =>
// Check for user
if (!user)
errors.email = "User not found";
return res.status(404).json(errors);
// Check Password
bcrypt.compare(password, user.password).then(isMatch =>
if (isMatch)
// User Matched
const payload =
id: user.id,
name: user.name,
admin: user.adminLevel
; // Create JWT Payload
// Sign Token
jwt.sign(
payload,
keys.secretOrKey,
expiresIn: 3600 ,
(err, token) =>
res.json(
success: true,
token: "Bearer " + token
);
);
else
errors.password = "Password incorrect";
return res.status(400).json(errors);
);
);
);
// @route GET api/users
// @desc Get users
// @access Public
router.get("/", (req, res) =>
User.find()
.sort( date: -1 )
.then(users =>
console.log("get", users), res.json(users);
)
.catch(err => res.status(404).json( nousersfound: "No users found" ));
);
// @route GET api/users/:id
// @desc Get eventful by id
// @access Public
router.get("/:id", (req, res) =>
User.findById(req.params.id)
.then(user =>
console.log(user), res.json(user);
)
.catch(err =>
res.status(404).json( nouserfound: "No user found with that ID" )
);
);
// @route POST api/users/:id
// @desc change user to admin
// @access Private
router.post(
"/:id",
passport.authenticate("jwt", session: false ),
(req, res) =>
User.findOne( _id: req.params.id )
.then(user =>
console.log("1231231231", user);
if (user)
if(user.adminLevel)
user.adminLevel = false;
else
user.adminLevel = true;
user.save().then(user => res.json(user));
)
.catch(err => res.status(404).json( usernotfound: "No post found" ));
);
// @route GET api/users/current
// @desc Return current user
// @access Private
router.get(
"/current",
passport.authenticate("jwt", session: false ),
(req, res) =>
res.json(
id: req.user.id,
name: req.user.name,
email: req.user.email,
admin: req.user.adminLevel
);
);
// @route DELETE api/users
// @desc Delete user
// @access Private
router.delete(
"/",
passport.authenticate("jwt", session: false ),
(req, res) =>
console.log("at route", req.body);
User.findOneAndRemove( _id: req.user.id ).then(() =>
res.json( success: true )
);
);
module.exports = router;
【问题讨论】:
我只是想为以后遇到同样问题的人写下我的答案。我在 405 卡了 4 个小时。 我只想提一下,也许 nginx .conf 文件不是唯一可以找到问题的地方 在我查看了我的代码后,我明白这不是 nginx 问题,而是后端问题。在我的用户登录代码中,我验证令牌的地方,我向前端而不是后端本身发送请求......真可惜......我修复了它,我的应用程序现在运行良好... 【参考方案1】:您的 nginx 配置错误。要通过 nginx 公开节点应用程序,您需要 Reverse Proxy 我已经回答了 related question
不使用 SSL 的反向代理的 nginx 配置。 服务器。
server
listen 80;
server_name example.com;
location /
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
使用 SSL
server
listen 443;
server_name example.com;
ssl_certificate /etc/letsencrypt/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/privkey.pem;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location /
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Fix the “It appears that your reverse proxy set up is broken" error.
proxy_pass http://localhost:3000;
proxy_read_timeout 90s;
proxy_redirect http://localhost:3000 https://example.com;
在example.com
中,您输入了您已使用您的 IP 注册的域。
如果您没有域,可以通过将其添加到主机中来测试它How to add an IP to hostname file
示例
127.0.0.1 example.com
无论您在哪里看到http://localhost:3000;
,您都会将internal 节点应用的IP 和端口放在哪里。如果它在同一台机器上,您将其保留为 localhost:port。
编辑 1
在你的情况下
server
listen 80;
server_name lovechangingworld.org;
location /
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
编辑 2
要让nodemailer 工作,有两种方法。假设nodemailer
在端口localhost:3000
上运行,要么使用lovechangingworld.org:8088
之类的端口,要么创建mail.lovechangingworld.org
之类的子域。
在sites-available
touch mail.lovechangingworld.org
中创建文件
2.添加配置
示例 1 个新子域:
server
listen 80;
server_name mail.lovechangingworld.org;
location /
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
示例 2 不同的端口:
server
listen 8088;
server_name lovechangingworld.org;
location /
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
【讨论】:
像这样???服务器听80; server_name lovechangingworld.org:8000;位置 / proxy_pass localhost:3000; proxy_http_version 1.1; proxy_set_header 升级 $http_upgrade; proxy_set_header 连接“升级”; proxy_set_header 主机 $host; proxy_cache_bypass $http_upgrade;这不起作用,同样的错误。我很困惑没有 SSL。我使用 SSL 登录 ubuntu。我用哪一个? 你在哪个端口启动 nodeJS 应用程序? 8000端口?在这种情况下,从域名中删除 8000 并保留为lovechangingworld.org
并将 localhost:3000
替换为 localhost:8000;
。我在你的回答中添加了一个示例,使用端口 8000
好的。我也试过了。这是我尝试过的最后一件事,但仍然无法正常工作。在 pm2 状态下,一些错误已经消失。但仍然给我 405 不允许的方法
lovechangingworld.org
指向你节点服务器的IP地址吗?
也许你还有其他配置?【参考方案2】:
server_name
应该是服务器名称,您提供的是文档根目录。
在服务器上运行您的节点应用程序,并在您的 Nginx conf 中为您的节点应用程序提供 reverse proxy
。
您可以使用 This doc 设置 Nodejs 应用程序以进行生产
【讨论】:
以上是关于加载资源失败:服务器响应状态为 405(不允许)需要有关 nginx.conf 的帮助的主要内容,如果未能解决你的问题,请参考以下文章
加载资源失败:服务器响应状态为 405(不允许)需要有关 nginx.conf 的帮助