OPTIONS预检请求后,节点+ Express服务器未响应 [英] Node + Express server not responding after OPTIONS preflight request

查看:122
本文介绍了OPTIONS预检请求后,节点+ Express服务器未响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前遇到以下错误,我正在节点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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆