【问题标题】:Cross-Origin Request Blocked even with headers跨域请求即使带有标头也被阻止
【发布时间】:2021-09-11 13:52:07
【问题描述】:

我在尝试从我的 vue 应用程序执行获取请求时收到此错误。我正在运行一个连接到我的本地 Mysql 服务器的 Express Node.js Express 应用程序。我已经设置了标头以允许在 localhost:8081 上运行的 Vue 应用程序访问节点服务器,但我仍然收到错误消息。我在 node 和 vue 上安装了 CORS。我的队友正在使用与我相同的代码,但没有收到此代码,但我仍然收到 CORS 错误(image for errors)。任何帮助将不胜感激。谢谢!

我的节点服务器的app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

const cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/courses');

var app = express();

var corsOptions = {
  origin: 'http://localhost:8081',
}

app.use(cors(corsOptions));
app.options('*', cors());

app.get('http://localhost:8081', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(function (req, res, next) {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

var mysql = require("mysql");
app.use(function(req, res, next){
  res.locals.connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '',
    database: 'course'
  })
  res.locals.connection.connect();
  next();
});


app.use('/api', indexRouter);
app.use('/api/courses', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});



module.exports = app;

course-services.js 用于我的节点应用程序的休息请求

import axios from "axios";

var baseurl = "";
if (process.env.NODE_ENV === "development") {
  baseurl = "http://localhost/api/";
} else {
  baseurl = "/api/";
}

const apiClient = axios.create({
  baseURL: baseurl,
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest",
    "Access-Control-Allow-Origin" : "*",
    crossDomain: true
  },
  transformRequest: (data, headers) => {
    let token = localStorage.getItem("token");
    let authHeader = "";
    if (token != null && token != "") authHeader = "Bearer " + token;
    headers.common["Authorization"] = authHeader;
    return JSON.stringify(data);
  },
  transformResponse: function(data) {
    data = JSON.parse(data);
    if (!data.success && data.code == "expired-session") {
      localStorage.deleteItem("token");
    }
    return data;
  }
});

export default {
  getCourses() {
    return apiClient.get("courses");
  },
  getCourse(id) {
    return apiClient.get("courses/" + id);
  },
  addCourse(course) {
    return apiClient.post("courses", course);
  },
  updateCourse(courseId, course) {
    return apiClient.put("courses/" + courseId, course);
  },
  deleteCourse(courseId) {
    return apiClient.delete("courses/" + courseId);
  },
};

【问题讨论】:

  • 在浏览器中,默认情况下,在每次 API 调用之前,浏览器本身都会向 url 发送一个OPTIONS 请求并检查响应状态。将 OPTIONS 处理程序添加到您的 api,然后重试。
  • @Saeed 这只是真的,如果传入的请求不是“简单”请求,也就是它有额外的标头、cookie 等

标签: javascript node.js express


【解决方案1】:

如果你使用 cors() 模块,我不知道为什么你多次设置标题,你不必再次设置标题

var corsOptions = {
  origin: 'http://localhost:8081',
}

app.use(cors(corsOptions));
app.options('*', cors());

这条路由就足够了,可以用作某些路由的中间件最后,只从http://localhost:8081 获取不要从任何随机的 chrome 开发控制台获取,这将在您将特定端口和域设置为 localhost 时使用暴力 cors 策略: 8081,请检查您是否使用 127.0.0.1:8081,如果是,它会再次抛出错误

only use http://localhost:8081 如果您使用 127.0.0.1 将无法正常工作,因为主机不匹配 希望这对您的问题有所帮助

【讨论】:

    【解决方案2】:

    您的请求中有一个自定义标头:
    "X-Requested-With": "XMLHttpRequest",

    您需要从请求标头中删除它,或者您需要通过在“Access-Control-Allow-Headers”中设置它来在服务器响应标头中支持它: 如果您认为可能有更多自定义标头,只需将其设置为 *

    res.setHeader('Access-Control-Allow-Headers', '*');
    

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers

    【讨论】:

    • Content-Type 如果其值为application/json,则也算作自定义标头。也许还有Access-Control-Allow-Origin(我不希望在请求中)。
    • Content-Type 不是自定义标头 developer.mozilla.org/en-US/docs/Web/HTTP/Headers 和 Access-Control-Allow-Origin 仅用于来自服务器的响应标头
    • 我的意思是:Content-Type: application/json 不是CORS-safelisted request header
    猜你喜欢
    • 2018-06-13
    • 2021-03-23
    • 2019-09-10
    • 2016-01-21
    • 2021-06-26
    • 2014-10-13
    • 1970-01-01
    相关资源
    最近更新 更多