Как разрешить CORS?

Я пытаюсь поддерживать CORS в моем узле.JS приложение, которое использует Экспресс.JS web framework. Я читал обсуждение группы Google о том, как справиться с этим, и прочитайте несколько статей о том, как работает CORS. Во-первых, я сделал это (код написан в синтаксисе CoffeeScript):

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

похоже, это не работает. Похоже, что мой браузер (Chrome) не отправляет запрос начальных параметров. Когда я только что обновил блок для ресурса, мне нужно отправить cross-origin получить запрос на:

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

Он работает (в Chrome). Это также работает в Safari.

Я читал, что...

в браузере, реализующем CORS, каждому запросу GET или POST перекрестного происхождения предшествует запрос OPTIONS, который проверяет, является ли GET или POST OK.

Итак, мой главный вопрос: почему это не происходит в моем случае? Почему это не мое приложение.варианты блока называются? Почему мне нужно установить заголовки в моем главное приложение.получить блок?

22 ответов


чтобы ответить на ваш главный вопрос, спецификация CORS требует только вызова опций, чтобы предшествовать сообщению или GET, если сообщение или GET имеет в нем какой-либо не простой контент или заголовки.

типы контента, требующие запроса CORS перед полетом (вызов опций), являются любым типом контента за исключением:

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

любые другие типы контента, кроме перечисленных выше вызовет запрос перед полетом.

как для заголовков, заголовков запроса только после вызовет запрос перед полетом:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. Width

любые другие заголовки запросов вызовут предварительный полет запрос.

таким образом, вы можете добавить пользовательский заголовок, такой как:x-Trigger: CORS, и это должно вызвать запрос перед полетом и нажать блок опций.

посмотреть MDN Web API Reference-CORS Preflighted requests


Я нашел самый простой способ-использовать узел.пакет Яш cors. Самое простое использование:

var cors = require('cors')

var app = express()
app.use(cors())

есть, конечно, много способов настроить поведение для ваших нужд; страница, связанная выше, показывает ряд примеров.


попробуйте передать управление следующему соответствующему маршруту. Если Express соответствует приложению.сначала получите маршрут, затем он не будет продолжаться на маршруте опций, если вы не сделаете это (обратите внимание на использование next):

app.get('somethingelse', function(req, res, next) {
    //..set headers etc.

    next();
});

С точки зрения организации материала CORS, я помещаю его в промежуточное ПО, которое хорошо работает для меня:

//CORS middleware
var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'example.com');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

    next();
}

//...
app.configure(function() {
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'cool beans' }));
    app.use(express.methodOverride());
    app.use(allowCrossDomain);
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});

чтобы остаться в той же идее маршрутизации. Я использую этот код :

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

подобно http://enable-cors.org/server_expressjs.html пример


do

npm install cors --save

и просто добавьте эти строки в свой основной файл, куда направляется ваш запрос.

const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());

Я сделал более полное промежуточное ПО, подходящее для express или connect. Он поддерживает OPTIONS запросы на предполетную проверку. Обратите внимание, что это позволит CORS доступ ко всему, вы можете поставить некоторые проверки, если вы хотите ограничить доступ.

app.use(function(req, res, next) {
    var oneof = false;
    if(req.headers.origin) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        oneof = true;
    }
    if(req.headers['access-control-request-method']) {
        res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
        oneof = true;
    }
    if(req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
        oneof = true;
    }
    if(oneof) {
        res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
    }

    // intercept OPTIONS method
    if (oneof && req.method == 'OPTIONS') {
        res.send(200);
    }
    else {
        next();
    }
});

установите модуль cors expressjs. вы можете выполнить следующие действия >

установка

npm install cors

простое использование (включить все запросы CORS)

var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());

для более подробной информации перейдите к https://github.com/expressjs/cors


сделать что-то вроде этого:

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

тестирование выполняется с помощью express + node + ionic в портах differente.

Localhost:8100

Localhost:5000

// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests

app.all('*', function(req, res, next) {
       res.header("Access-Control-Allow-Origin", "*");
       res.header("Access-Control-Allow-Headers", "X-Requested-With");
       res.header('Access-Control-Allow-Headers', 'Content-Type');
       next();
});

сначала просто установите cors в свой проект. Взять терминал(командная строка) и cd в каталог проекта и выполните следующую команду:

npm install cors --save
сервер.JS файл и измените код, чтобы добавить в нем следующее:
var cors = require('cors');


var app = express();

app.use(cors());

app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   next();
});

это работает для меня..


это работает для меня, так как его простая реализация внутри маршрутов, im с помощью meanjs и его работы отлично, safari, chrome и т. д.

app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){ 
        res.header('Access-Control-Allow-Origin', '*'); 
        res.header('Access-Control-Allow-Methods', 'GET, POST');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        return res.send(200);

    });

некоторое время назад я столкнулся с этой проблемой, поэтому я сделал это, чтобы разрешить CORS в моем приложении nodejs:

сначала ты нужно установить cors С помощью команды ниже:

npm install cors --save

теперь добавить следующий код в ваше приложение, начиная файл, как ( app.js or server.js)

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);

Если вы хотите сделать его конкретным контроллером, вы можете использовать:

res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');

обратите внимание, что это также позволит iframes.


мое самое простое решение с Express 4.2.0 (EDIT: похоже, не работает в 4.3.0) было:

function supportCrossOriginScript(req, res, next) {
    res.status(200);
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type");

    // res.header("Access-Control-Allow-Headers", "Origin");
    // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // res.header("Access-Control-Allow-Methods","POST, OPTIONS");
    // res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
    // res.header("Access-Control-Max-Age","1728000");
    next();
}

// Support CORS
app.options('/result', supportCrossOriginScript);

app.post('/result', supportCrossOriginScript, function(req, res) {
    res.send('received');
    // do stuff with req
});

Я полагаю, что делаю app.all('/result', ...) тоже будет работать...


в дополнение к тому, что говорили другие, не забывайте, что, если вы не используете nodemon, вам нужно будет перезапустить сервер узлов, чтобы изменения вступили в силу!

Я лично обновлял свой браузер по привычке, забывая, что это код на стороне сервера.


Я обнаружил, что это очень легко сделать с пакетом запросов npm (https://www.npmjs.com/package/request)

тогда я основал свое решение на этом посте http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/

'use strict'

const express = require('express');
const request = require('request');

let proxyConfig = {
    url : {
        base: 'http://servertoreach.com?id=',
    }
}

/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);


/* methods forwarded to the servertoreach proxy  */
server.use('/somethingElse', function(req, res)
{
    let url = proxyConfig.url.base + req.query.id;
    req.pipe(request(url)).pipe(res);
});


/* start the server */
server.listen(server.get('port'), function() {
    console.log('express server with a proxy listening on port ' + server.get('port'));
});

мы можем избежать CORS и перенаправить запросы на другой сервер вместо этого:

// config:
var public_folder = __dirname + '/public'
var apiServerHost = 'http://other.server'

// code:
console.log("starting server...");

var express = require('express');
var app = express();
var request = require('request');

// serve static files
app.use(express.static(public_folder));

// if not found, serve from another server
app.use(function(req, res) {
    var url = apiServerHost + req.url;
    req.pipe(request(url)).pipe(res);
});

app.listen(80, function(){
    console.log("server ready");
});

я использовал следующие шаги для моего веб-приложения, и у меня был успех:

добавьте пакет cors в express:

npm install cors --save

добавить следующие строки после настройки bodyParser. У меня были некоторые проблемы с добавлением перед bodyParser:

 // enable cors to the server
const corsOpt = {
    origin: process.env.CORS_ALLOW_ORIGIN || '*', // this work well to configure origin url in the server
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
    allowedHeaders: ['Content-Type', 'Authorization'] // allow json and token in the headers
};
app.use(cors(corsOpt)); // cors for all the routes of the application
app.options('*', cors(corsOpt)); // automatic cors gen for HTTP verbs in all routes, This can be redundant but I kept to be sure that will always work.

использование Express Middleware отлично подходит для меня. Если вы уже используете Express, просто добавьте следующие правила промежуточного ПО. Он должен начать работать.

app.all("/api/*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
  return next();
});

app.all("/api/*", function(req, res, next) {
  if (req.method.toLowerCase() !== "options") {
    return next();
  }
  return res.send(204);
});

ссылка


см. код ниже то же самое. Источник:Academind / node-restful-api

const express = require('express');
const app = express();

//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
    res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
    );
    if(req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
        return res.status(200).json({});
    }
    next(); //so that other routes can take over
})

ниже код будет работать ,но сначала установить кеш на:

npm install --save cors

затем:

module.exports = function(app) { 
var express = require("express");
var cors = require('cors');
var router = express.Router();
app.use(cors());

app.post("/movies",cors(), function(req, res) { 
res.send("test");
});

в TypeScript, если вы хотите использовать узел.пакет Яш cors

/**
* app.ts
* If you use the cors library
*/

import * as express from "express";
[...]
import * as cors from 'cors';

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       const corsOptions: cors.CorsOptions = {
           origin: 'http://example.com',
           optionsSuccessStatus: 200
       };
       this.express.use(cors(corsOptions));
   }
}

export default new App().express;

Если вы не хотите использовать библиотеки третьей части для обработки ошибок cors, вам нужно изменить метод handleCORSErrors ().

/**
* app.ts
* If you do not use the cors library
*/

import * as express from "express";
[...]

class App {
   public express: express.Application;

   constructor() {
       this.express = express();
       [..]
       this.handleCORSErrors();
   }

   private handleCORSErrors(): any {
       this.express.use((req, res, next) => {
           res.header("Access-Control-Allow-Origin", "*");
           res.header(
               "Access-Control-ALlow-Headers",
               "Origin, X-Requested-With, Content-Type, Accept, Authorization"
           );
           if (req.method === "OPTIONS") {
               res.header(
                   "Access-Control-Allow-Methods",
                   "PUT, POST, PATCH, GET, DELETE"
               );
               return res.status(200).json({});
           } 
           next(); // send the request to the next middleware
       });
    }
}

export default new App().express;

для использования приложения.файл TS

/**
* server.ts
*/
import * as http from "http";
import app from "./app";

const server: http.Server = http.createServer(app);

const PORT: any = process.env.PORT || 3000;
server.listen(PORT);