OPTIONS预检请求后,节点+ Express服务器未响应 [英] Node + Express server not responding after OPTIONS preflight request
问题描述
我目前遇到以下错误,我正在节点js中开发一个虚拟商店的API。为了将其物品放入购物车,用户需要进行身份验证。身份验证是通过JWT处理的,我使用该提议的护照模块。
I'm currently facing the following error, I'm developing an API in node js for let's say a virtual shop. An user, for getting its items in cart needs to be authenticated. The authentication is being handled via JWT, and im using passport module for that propose.
对于需要身份验证的路由,当使用 Authentication标头使用API时服务器使用其对应的 JWT ey ...令牌,未处理任何请求。只需响应OPTIONS飞行前请求,仅此而已。
我尝试使用httpClient和授权标头从有角前端使用/ api / cart,并在chrome devTools中得到以下错误
For the routes that require authentication, when the API is consumed using the 'Authentication' header with its correspondent 'JWT ey...' token, the server is not handling any request. Just responds to the OPTIONS preflight request and nothing more. I've tried consuming the /api/cart from an angular front end using httpClient, and the authorization header and getting the following error in the chrome devTools
我也尝试过使用邮递员,发送授权标头,并且无法得到任何响应屏幕出现。
As well i've tried using postman, sending the authorization header and couldn't get any response screen appears.
我正在记录OPTIONS请求标头。以下是使用授权标头敲击/ api / cart后服务器的响应,并在此处停止。
I'm logging the OPTIONS request headers. The following is the server response after hitting /api/cart with authorization header and it stops there.
!OPTIONS
{ host: 'localhost:3000',
connection: 'keep-alive',
'access-control-request-method': 'GET',
origin: 'http://localhost:4200',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36',
'access-control-request-headers': 'authorization,content-type',
accept: '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9' }
!OPTIONS
OPTIONS /api/cart 200 1.288 ms - -
server.js
server.js
const mongoose = require("mongoose");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const passport = require("passport");
const config = require("./config/database"); //Getting databas config file
const User = require("./app/models/user"); //we're getting mongoose model
const Product = require("./app/models/product");
const app = express();
const port = process.env.PORT || 3000;
const routes = require("./app/routes/index");
mongoose.connect(config.database);
//bodyParser to get our request/response parameters
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json({ limit: "50mb" }));
//log request to console
app.use(morgan("dev"));
app.use(passport.initialize());
//pass passport for connfiguration
require("./config/passport")(passport);
//allow cors
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, OPTIONS, PUT, PATCH, DELETE"
);
if (req.method === "OPTIONS") {
console.log("!OPTIONS");
res.end();
}
next();
});
routes(app);
app.listen(port);
console.log("express app started on port " + port);
routes / index.js
routes/index.js
const productApiRouter = require("./product.routes");
const userApiRouter = require("./user.routes");
module.exports = (app) => {
app.use("/api", userApiRouter); //routes for users
app.use("/products", productApiRouter); // routes for products
};
routes / user.routes
routes/user.routes
require('../models/user')
const express = require('express');
const passport = require('passport')
const isAuthenticated = require('../controllers/auth.controller')
const router = express.Router();
var userController = require('../controllers/user.controller');
router.get('/', userController.getUser)
router.get('/cart', passport.authenticate('jwt', {
session: false,
failWithError: true
}), userController.getCart)
router.post('/deletecart/:id', userController.deleteCartById)
router.post('/authenticate', userController.authenticate)
router.post('/signup', userController.signupUser)
router.get('/verify_email', userController.verifyEmailByUrl)
router.post('/addcart/:id', userController.addItemToCart)
router.post('/update_user', userController.updateUser)
module.exports = router;
controllers / user.controller.js
获取购物车方法
controllers/user.controller.js get cart method
exports.getCart = (req, res) => {
var token = getToken(req.headers);
if (token) {
var decoded = jwt.decode(token, config.secret);
User.findOne(
{
email: decoded.email
},
function(err, user) {
if (err) throw err;
if (!user) {
return res.status(404).send({
success: false,
message: "Not user found"
});
} else {
var cart = user.itemsInCart;
console.log(cart);
var items = addItemCount.addItemCount(cart);
console.log(items);
res.status(200).send(JSON.stringify(items));
}
}
);
} else {
console.log('Request ')
res.status(403).send({
success: false,
message: "Unauthorized request"
});
}
};
配置/护照--->护照配置
config/passport ---> passport configuration
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const User = require('../app/models/user');
const config = require('./database');
//add a JWT strategy to our passport
module.exports = function(passport) {
var opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("jwt");
opts.secretOrKey = config.secret;
passport.use('jwt', new JwtStrategy(opts, function(jwt_payload, done) {
User.findOne({
id: jwt_payload.id //try to find a user given jwt_payload.id
}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false)
}
});
}));
}
getToken函数
getToken function
var getToken = function(headers) {
if (headers && headers.authorization) {
var parted = headers.authorization.split(' ');
if (parted.length === 2) {
return parted[1];
} else {
return null;
}
} else {
return null;
}
};
module.exports = getToken
推荐答案
解决问题后,我发现服务器无法使用授权令牌进行请求的原因。
After struggling the problem I found the reason the server is not working for request with authorization token.
对于NodeJS服务器,标头的HTTP请求的最大大小为 80KB
。参考: http_parser.h nodejs源代码
For a NodeJS server, the header's max size for http requests is 80KB
. ref: http_parser.h nodejs source code
#define HTTP_MAX_HEADER_SIZE (80*1024)
在问题中提到的请求中,我将一些Base64编码的图像附加到JWT令牌,使其比NodeJS允许的标头大小更大
In the mentioned requests in the question, I'm attaching some Base64 encoded images to the JWT Token making it way more bigger than the header size permitted by the NodeJS server for http requests.
因此,解决方案是确保http请求的标头大小小于 80K
阈值。
So the solution is to make sure that the headers size for an http request is below 80K
threshold.
这篇关于OPTIONS预检请求后,节点+ Express服务器未响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!