Нет «Access-Control-Allow-Origin» - проблема с узлом / портом Apache

260

я создал небольшой API с помощью Node / Express и пытаюсь получить данные с помощью Angularjs, но поскольку моя html-страница работает под apache на localhost: 8888 и API-интерфейс узла прослушивает порт 3000, я получаю No 'Access-Control- Allow-Origin'. Я пытался использовать node-http-proxyVhosts Apache, но безуспешно, смотрите полную ошибку и код ниже.

XMLHttpRequest не может загрузить localhost: 3000. В запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Origin 'localhost: 8888', следовательно, не разрешен доступ. "

// Api Using Node/Express    
var express = require('express');
var app = express();
var contractors = [
    {   
     "id": "1", 
        "name": "Joe Blogg",
        "Weeks": 3,
        "Photo": "1.png"
    }
];

app.use(express.bodyParser());

app.get('/', function(req, res) {
  res.json(contractors);
});
app.listen(process.env.PORT || 3000);
console.log('Server is running on Port 3000')

Угловой код

angular.module('contractorsApp', [])
.controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').then(function(response) {
       var data = response.data;
       $scope.contractors = data;
   })

HTML

<body ng-app="contractorsApp">
    <div ng-controller="ContractorsCtrl"> 
        <ul>
            <li ng-repeat="person in contractors">{{person.name}}</li>
        </ul>
    </div>
</body>
user1336103
источник

Ответы:

622

Попробуйте добавить следующее промежуточное ПО в ваше приложение NodeJS / Express (для вашего удобства я добавил несколько комментариев):

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // 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');

    // 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();
});

Надеюсь, это поможет!

jvandemo
источник
2
Можете ли вы помочь точно указать, куда это идет? У меня есть следующий код на моем сервере. Это идет сразу после этого? var app = require ('express') (), server = require ('http'). createServer (app), io = require ('socket.io'). listen (server), request = require ("request") , url = require ("url"); server.listen (6969); // это идет здесь? на новой линии?
Арт Гейгель
1
@jvandemo мне нужно изменить app.get ('/', function (req, res) на ... function (req, res, next)?
Санграм Сингх
10
Ты мой любимый человек когда-либо прямо сейчас. Спасибо. Можем ли мы добавить примечание, что этот код должен произойти до того, как будут определены маршруты для таких нубов, как я?
Gegillam
1
Как заставить это работать при использовании модуля запроса?
Рохит Тигга
2
Это не сработало в моем случае. По-прежнему появляется сообщение об ошибке: «Ответ на запрос предварительной проверки не проходит проверку контроля доступа: на запрошенном ресурсе отсутствует заголовок« Access-Control-Allow-Origin ». Следовательно, источник« abc.xyz.net:212 »не разрешен Доступ. Ответ имеет HTTP-код состояния 500. "
user1451111
96

Принятый ответ - хорошо, если вы предпочитаете что-то более короткое, вы можете использовать плагин cors, доступный для Express.js

Это просто в использовании, для этого конкретного случая:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));
Фабиано Сориани
источник
3
Я должен был использовать {origin: 'null'}его для работы ... Судя по всему, мой браузер отправляет nullв качестве источника?
Рикардо Круз
2
Зачем изобретать велосипед. Я всегда за пакетное решение по сравнению с фрагментом кода
Pierre
милая маленькая библиотека, которая справилась с моим сценарием использования: очень приятно хотеть разные методы из разных источников ... и меньше усталости кода для следующего парня, который смотрит на это.
Кайл Бейкер
6
Спасибо, app.use(cors({origin: '*'}));сработало для меня, согласно enable-cors .
Даниалк
2
Я предлагаю заглянуть на страницу npm cors, чтобы лучше ее использовать. Это сделало вещи очень понятными для меня =).
13013SwagR
30

Другой способ, просто добавьте заголовки к вашему маршруту:

router.get('/', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // If needed
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // If needed
    res.setHeader('Access-Control-Allow-Credentials', true); // If needed

    res.send('cors problem fixed:)');
});
Асаф Хананель
источник
8
)смайлик меня смутил
diEcho
17

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

Кроме того, топовый ответ страдает от того факта, что OPTIONSзапрос не обрабатывается промежуточным ПО, и вы не получаете его автоматически.

Я сохраняю домены в белом списке, как allowed_originsв конфигурации Express, и помещаю правильный домен в соответствии с originзаголовком, поскольку Access-Control-Allow-Originне позволяет указывать более одного домена.

Вот чем я закончил:

var _ = require('underscore');

function allowCrossDomain(req, res, next) {
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');

  var origin = req.headers.origin;
  if (_.contains(app.get('allowed_origins'), origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

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

app.configure(function () {
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(allowCrossDomain);
});
Дан Абрамов
источник
Это то же самое 'if (app.get (' разрешено происхождение '). IndexOf (origin)! == - 1)?'?
Руна Джеппезен
13

Код ответа разрешен только для localhost: 8888. Этот код не может быть развернут на производстве или на другом сервере и имени порта.

Чтобы заставить это работать для всех источников, используйте это вместо этого:

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // 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');

    // 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();
});
Vicheanak
источник
2
Это не работает для меня! «* не является допустимым источником». Кажется, символ * не распознается как подстановочный знак.
Франческо
Меня устраивает. то есть используя подстановочный знак '*'. работает как для хрома, так и для сафари.
AnBisw
Спасибо;) Отлично работает
Mauro
9

Установите зависимость cors в вашем проекте:

npm i --save cors

Добавьте в свой файл конфигурации сервера следующее:

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

У меня работает с версией 2.8.4 cors.

monikaja
источник
"cors": "^2.8.5", "express": "^4.16.3",отлично работает только с предложенной строкой @monikaja. Спасибо!
RamiroIsBack
Это позволяет всем источникам / доменам получать доступ к приложению, чего вы обычно не хотите делать. Вместо этого укажите только разрешенные домены.
Лачо Томов
7

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

app.get('/', function (req, res) {

    res.header("Access-Control-Allow-Origin", "*");
    res.send('hello world')
})

Вы можете изменить *, чтобы соответствовать вашим потребностям. Надеюсь, это поможет.

DMX
источник
7

Привет это происходит, когда интерфейс и бэкэнд работает на разных портах. Браузер блокирует ответы от бэкэнда из-за отсутствия заголовков CORS. Решение состоит в том, чтобы добавить заголовки CORS в бэкэнд-запрос. Самый простой способ - использовать пакет cors npm.

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

Это включит заголовки CORS во всех ваших запросах. Для получения дополнительной информации вы можете обратиться к документации Cors

https://www.npmjs.com/package/cors

Картик
источник
3
app.all('*', function(req, res,next) {
    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

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


});
Wiki
источник
2

Добавьте следующий код в app.js NODEJ Restful api, чтобы избежать ошибки «Access-Control-Allow-Origin» в angular 6 или любой другой платформе

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
}));
Ежил Арасан
источник
1

Вы можете использовать "$ http.jsonp"

ИЛИ

Ниже представлен обход хрома для локального тестирования.

Вам нужно открыть свой хром с помощью следующей команды. (Нажмите окно + R)

Chrome.exe --allow-file-access-from-files

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

Если вы вводите эту команду в командной строке, выберите каталог установки Chrome и используйте эту команду.

Ниже приведен код скрипта для открытого chrome в MAC с «--allow-file-access-from-files»

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"

второй вариант

Вы можете просто использовать open (1) для добавления флагов: open -a 'Google Chrome' --args --allow-file-access-from-files

JQuery Гуру
источник
Как насчет MAC? Chrome.exe - допустимый доступ к файлам из файлов
user1336103
/ Applications / Google \ Chrome.app/Contents/MacOS/Google \ Chrome --allow-file-access-from-files удается открыть chrome, но по-прежнему отображается сообщение «XMLHttpRequest не может загрузить localhost: 3000. Источник localhost: 8888 is не разрешено Access-Control-Allow-Origin. "
user1336103
+1 Я могу подтвердить, что это работает с опцией Mac, используя «open». Мой случай немного отличается, так как я просто тестирую полностью загруженный сайт, который обращается к некоторым локальным файлам JSON.
Спонг
0

/**
 * Allow cross origin to access our /public directory from any site.
 * Make sure this header option is defined before defining of static path to /public directory
 */
expressApp.use('/public',function(req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // Set to true if you need the website to include cookies in the requests sent
    res.setHeader('Access-Control-Allow-Credentials', true);
    // Pass to next layer of middleware
    next();
});


/**
 * Server is about set up. Now track for css/js/images request from the 
 * browser directly. Send static resources from "./public" directory. 
 */
expressApp.use('/public', express.static(path.join(__dirname, 'public')));
If you want to set Access-Control-Allow-Origin to a specific static directory you can set the following.

Лутон Датта
источник