Разрешить запрос CORS REST в приложение Express/Node.js на Heroku

Я написал REST API в express framework для node.js, который работает для запросов из консоли js в Chrome, а также в строке URL и т.д. Теперь я пытаюсь заставить его работать для запросов от другого app, в другом домене (CORS).

Первый запрос, сделанный автоматически передним концом javascript, заключается в /api/search? uri = и, похоже, не работает в запросе OPTIONS "предполетный".

В моем экспресс-приложении я добавляю заголовки CORS, используя:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

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

и

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(allowCrossDomain);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

С консоли Chrome я получаю следующие заголовки:

URL-адрес запроса: http://furious-night-5419.herokuapp.com/api/search? uri = http% 3A% 2F% 2Flocalhost% 3A5000% 2Fcollections% 2F1% 2Fdocuments% 2F1

Метод запроса: ОПЦИИ

Код состояния: 200 OK

Заголовок запроса

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, x-annotator-auth-token, accept
Access-Control-Request-Method:GET
Connection:keep-alive
Host:furious-night-5419.herokuapp.com
Origin:http://localhost:5000
Referer:http://localhost:5000/collections/1/documents/1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5

Параметры строки запроса

uri:http://localhost:5000/collections/1/documents/1

Заголовки ответов

Allow:GET
Connection:keep-alive
Content-Length:3
Content-Type:text/html; charset=utf-8
X-Powered-By:Express

Это похоже на отсутствие правильных заголовков, отправляемых приложением API?

Спасибо.

Ответ 1

Я прочитал ваш код в чистом приложении ExpressJS, и он отлично работает.

Попробуйте переместить app.use(allowCrossDomain) в начало функции configure.

Ответ 2

для поддержки файлов cookie с помощью Credentials вам нужна эта строка xhr.withCredentials = true;

mdn docs xhr.withCredentials

В Express Server добавьте этот блок перед всеми другими

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

Ответ 3

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

Оказывается, что секретный токен JSON Web string не был определен в переменных среды, поэтому токен не может быть подписан. Это вызвало любой запрос POST, который полагается на проверку или подпись токена, чтобы получить тайм-аут и вернуть ошибку 503, сообщив браузеру, что в CORS что-то не так, что это не так. Добавление переменной среды в Heroku решило проблему.

Я надеюсь, что это поможет кому-то.

Ответ 4

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

Как отмечает @ConnorLeech в своем комментарии к принятому ответу выше, существует очень удобный пакет npm, который, как ни странно, называется cors. Его использование так же просто, как var cors = require('cors'); app.use(cors()); var cors = require('cors'); app.use(cors()); (опять же, заимствовано из ответа г-на Лича) и может также применяться более строгим и настраиваемым способом, как указано в их документах.

Также стоит отметить, что первоначальный комментарий, на который я ссылаюсь выше, был сделан в 2014 году. Сейчас 2019 год, и, глядя на страницу github пакета npm, репо было обновлено всего девять дней назад.