Дозволити запит CORS REST до програми Express / Node.js на Heroku


97

Я написав REST API на експрес-фреймворку для node.js, який працює для запитів із консолі js у Chrome, та URL-адреси тощо. Зараз я намагаюся змусити його працювати для запитів з іншого додатка, на іншому домен (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?

Дякую.


Я отримую цю помилку в коді, який я не писав, але я не розумію необхідності обробника OPTIONSметоду. Чи може хтось допомогти мені зрозуміти, чому б не обробляти лише POSTметод, а не обидва POST і OPTIONS метод?
Улісс Алвес,

Можна також включити, PATCHякщо ви будете використовувати його замість того, PUTщоб оновлювати ресурс
Денні,

Відповіді:


65

Я перевірив ваш код у чистому додатку ExpressJS, і він чудово працює.

Спробуйте перемістити свою app.use(allowCrossDomain)у верхню частину функції налаштування.


8
Причина цього полягає в тому, що вам потрібно визначити його перед app.use(app.router);ура!
Міхал

У моєму випадку наступний POST не викликається після відправки назад res.send (200), коли req.method == 'OPTIONS'. мені щось ще не вистачає?
Aldo

2Aldo: Потрібен код. Можливо, ви забули деякі заголовки? Якщо ваш клієнт не надсилає POST після того, як на ваш сервер належним чином подано попередній запит OPTIONS, спробуйте перевірити консоль інструментів розробника. WebKit реєструє такі помилки на консолі веб-інспектора.
Олегас,

1
@ConnorLeech Дуже приємно. Я робив підхід allowCrossDomain, як зазначено вище, і втомився мати справу з усіма тими заголовками mgmt. Крім того - оскільки CORS нам потрібен лише для розробників, не було сенсу приділяти стільки циклів з'ясуванню того, що відбувається. Радий, що є підтримка node.js для того, щоб легко це дозволити.
Стівен

1
@ConnorLeech Я думаю, що ви повинні додати свій коментар як відповідь ... працює як ласощі, і це приємно і просто
drmrbrewer

4

для підтримки файлів cookie за допомогою облікових даних вам потрібен цей рядок 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();
});`

4

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

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

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


0

Це не може бути для більшості людей, які переглядають це питання, але у мене була точно така ж проблема, і рішення не було пов'язане CORS.

Виявляється, секрет веб-маркера JSON stringне був визначений у змінних середовища, тому маркер не міг бути підписаний. Це призвело до того, що будь-який POSTзапит, який покладається на перевірку або підпис маркера, отримує час очікування та повертає 503помилку, повідомляючи браузеру, що щось не так CORS, а це не так. Додавання змінної середовища в Heroku вирішило проблему.

Сподіваюся, це комусь допомагає.


Так, це була проблема зі мною. Не могли б Ви конкретніше визначити, як Ви вирішили проблему. Я все ще перебуваю в розробці і працюю на пакеті Express.js з пакетом node cors.
Алан,

@alan Я використовував обіцянки для перевірки маркера в моїй програмі, дещо, як, якщо секрет JWT не визначений, обіцянка ніколи не вирішиться, ось код, який я використовував, якщо вам потрібні додаткові посилання.
CatBrownie

Дякуємо за відповідь. Я перегляну код. По секрету я припускаю, що ви говорите про другий приватний ключ. Я використовую oauth2.
Алан,

Додам, що будь-яка невідома обіцянка спричинить цю оманливу помилку! Мені довелося чітко сказати про те, яка версія Node використовується, інакше мої дзвінки до бази даних (mongo) просто зависали, і єдине, що міг сказати мені браузер, - це 503, а потім якась глупота, пов’язана з Cors. Ця помилка насправді збентежила мене найдовше, як я app.use(cors());ходив.
буквено-цифровий0101
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.