Как включить совместное использование ресурсов между источниками (CORS) в платформе express.js на node.js

101

Я пытаюсь создать веб-сервер в node.js, который будет поддерживать междоменные сценарии, но при этом будет предоставлять статические файлы из общедоступного каталога. Я использую express.js и не совсем уверен, как разрешить междоменный скриптинг ( Access-Control-Allow-Origin: *).

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

var express = require('express')
  , app = express.createServer();

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

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(app.router);
});

app.configure('development', function () {

    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {


    var oneYear = 31557600000;
    //    app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);
Парень
источник
Обратите внимание на app.all и app.get. Это запрос OPTIONS, а не GET
Шимон Дудкин
см. local-web-server для примера простого узла, статического веб-сервера, который поддерживает CORS
Ллойд
см. enable-cors.org/server_apache.html для получения дополнительной информации
Мостафа
"Access-Control-Allow-Origin", "*"делает ваш API интересным для фишинговых приложений. Рассмотрите возможность разрешения только известного происхождения.
Мартин Шнайдер

Ответы:

159

Проверять, выписываться пример с enable-cors.org :

В вашем приложении ExpressJS на node.js сделайте следующее со своими маршрутами:

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

app.get('/', function(req, res, next) {
  // Handle the get for this route
});

app.post('/', function(req, res, next) {
 // Handle the post for this route
});

Первый вызов ( app.all) должен быть выполнен перед всеми другими маршрутами в вашем приложении (или, по крайней мере, теми, которые вы хотите включить CORS).

[Редактировать]

Если вы хотите, чтобы заголовки отображались и для статических файлов, попробуйте это (убедитесь, что это перед вызовом use(express.static()):

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

Я проверил это с вашим кодом и получил заголовки активов из publicкаталога:

var express = require('express')
  , app = express.createServer();

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With");
      next();
    });
    app.use(app.router);
});

app.configure('development', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

Вы, конечно, можете упаковать функцию в модуль, чтобы сделать что-то вроде

// cors.js

module.exports = function() {
  return function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
  };
}

// server.js

cors = require('./cors');
app.use(cors());
Мишель Тилли
источник
Привет, спасибо за ответ. Я сделал то, что вы предложили (первая часть, но все еще не вижу разницы в заголовках запросов). Я приложил свой текущий код выше. не могли бы вы объяснить, как я могу интегрировать в это остальную часть вашего решения?
Guy
1
Я удивлен , что, так как вы useИНГ app.routerдо того, express.staticчто она не изменяет заголовки для статических файлов; в любом случае, я обновил свой ответ, чтобы он работал.
Мишель Тилли
Спасибо! Я вижу, что вы правы. Активы получены с сервера с запрошенными заголовками. Возможно, я не совсем понимал мою настоящую проблему. Я пытаюсь выполнить вызов API на внешний сервер с помощью команды get. и здесь я получаю сообщение об ошибке: XMLHttpRequest не может загрузить SOMEURL.com . Origin localhost: 8888 не разрешен Access-Control-Allow-Origin.
Guy
Я могу неправильно понять. Вы контролируете сервер на SOMEURL.com?
Мишель Тилли,
Извините, я полностью понимаю ваш ответ. Большое спасибо. Я ценю вашу помощь :)
Guy
58

После решения @Michelle Tilley, по-видимому, сначала это не сработало для меня. Не уверен, почему, возможно, я использую хром и другую версию узла. После внесения некоторых незначительных изменений он теперь работает для меня.

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

Если кто-то сталкивается с подобной проблемой, как моя, это может быть полезно.

Тони Такеши
источник
Обратите внимание на app.all и app.get. Это запрос OPTIONS, а не GET
Шимон Дудкин
У меня это работает (я получаю объекты с помощью Backbone). Я пытаюсь понять, будет ли он работать в IE 8 ... кажется, что он должен, но я не знаю, требуется ли что-то особенное для этой вещи "XDomainRequest" ... developer.mozilla.org/en- US / docs / HTTP /…
Адам Ловинг,
НЕКОТОРЫЕ ИНФОРМАЦИЯ ДЛЯ БУДУЩИХ ПОЛЬЗОВАТЕЛЕЙ: я перенаправляю свое доменное имя в репозиторий heroku, поэтому я столкнулся с этой проблемой. В любом случае, первый ответ работал локально, но не после того, как я отправил его на heroku. Однако этот ответ сработал после нажатия на героку.
Крис Холленбек
@KrisHollenbeck Это не работает для меня на heroku, ты делал что-нибудь еще?
Бен Крейг
@BenCraig, Нет, но у меня вообще перестало работать после первой попытки. Так что у меня все еще есть эта проблема.
Крис Холленбек
11

Попробуйте это cors npm modules.

var cors = require('cors')

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

Этот модуль предоставляет множество функций для точной настройки параметров cors, таких как белый список доменов, включение cors для конкретных API и т. Д.

Захид Рахман
источник
2

Я использую это:

var app = express();

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

h.readFiles('controllers').forEach(function(file){
  require('./controllers/' + file)(app);
})
;

app.listen(port);
console.log('server listening on port ' + port);

этот код предполагает, что ваши контроллеры находятся в каталоге контроллеров. каждый файл в этом каталоге должен выглядеть примерно так:

module.exports = function(app){

    app.get('/', function(req, res, next){
        res.end('hi');
    });

}
Элмер
источник
1

Рекомендуем использовать модуль cors express. Это позволяет вам заносить домены в белый список, разрешать / ограничивать домены специально для маршрутов и т. Д.

Джером Энтони
источник
0

Вы должны установить Access-Control-Allow-Credentials: true, если вы хотите использовать «cookie» через «Учетные данные»

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});
герцог
источник
0
app.use(function(req, res, next) {
var allowedOrigins = [
  "http://localhost:4200"
];
var origin = req.headers.origin;
console.log(origin)
console.log(allowedOrigins.indexOf(origin) > -1)
// Website you wish to allow to
if (allowedOrigins.indexOf(origin) > -1) {
  res.setHeader("Access-Control-Allow-Origin", origin);
}

// res.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");

// Request methods you wish to allow
res.setHeader(
  "Access-Control-Allow-Methods",
  "GET, POST, OPTIONS, PUT, PATCH, DELETE"
);

// Request headers you wish to allow
res.setHeader(
  "Access-Control-Allow-Headers",
  "X-Requested-With,content-type,Authorization"
);

// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader("Access-Control-Allow-Credentials", true);

// Pass to next layer of middleware
next();

});

Добавьте этот код в свой файл index.js или server.js и измените разрешенный исходный массив в соответствии с вашими требованиями.

Атес
источник
-6

Еще один шаг, который мне нужно было сделать, - это переключить мой URL-адрес с http://localhostнаhttp://127.0.0.0

пользователь3795430
источник
Что вы имеете в виду?
Blunderfest 01