Sem 'Acesso-controle-permissão-origem' - Problema na porta do nó / Apache


260

Eu criei uma pequena API usando o Node / Express e tentando extrair dados usando o Angularjs, mas como minha página html está sendo executada no apache no localhost: 8888 e a API do nó está escutando na porta 3000, estou recebendo o No 'Access-Control- Allow-Origin '. Eu tentei usar o node-http-proxyVhosts Apache, mas não tendo muito sucesso, veja o código e o erro completo abaixo.

XMLHttpRequest não pode carregar localhost: 3000. Nenhum cabeçalho 'Access-Control-Allow-Origin' está presente no recurso solicitado. Portanto, 'localhost local: 8888' de origem não é permitido. "

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

Código angular

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>

Respostas:


622

Tente adicionar o seguinte middleware ao seu aplicativo NodeJS / Express (adicionei alguns comentários para sua conveniência):

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

Espero que ajude!


2
Você pode ajudar a especificar exatamente para onde isso vai? Eu tenho o seguinte código no meu servidor. Vai logo depois disso? var app = requer ('express') (), servidor = requer ('http'). createServer (app), io = requer ('socket.io'). listen (servidor), request = require ("request") , url = require ("url"); server.listen (6969); // vai aqui? em uma nova linha?
Art Geigel

1
@jvandemo eu tenho que mudar o app.get ( '/', function (req, res) para ... function (req, res, ao lado)?
Sangram Singh

10
Você é minha pessoa favorita agora. Obrigado. Podemos adicionar uma observação de que esse código precisa acontecer antes que as rotas sejam definidas para noobs como eu?
Gegillam

1
Como fazer isso funcionar ao usar o módulo de solicitação?
precisa

2
Não funcionou no meu caso. Ainda obtendo este erro: "A resposta à solicitação de comprovação não passa na verificação de controle de acesso: nenhum cabeçalho 'Access-Control-Allow-Origin' está presente no recurso solicitado. Portanto, a origem ' abc.xyz.net:212 ' não é permitida A resposta tinha o código de status HTTP 500. "
user1451111

96

A resposta aceita é boa. Caso prefira algo mais curto, você pode usar um plugin chamado cors disponível para o Express.js

É simples de usar, neste caso em particular:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));

3
Eu tive que usar {origin: 'null'}para que ele funcionasse ... Aparentemente, meu navegador envia nullcomo origem?
Ricardo Cruz

2
Por que reinventar a roda. Estou sempre para uma solução integrada em relação ao trecho de código
Pierre

uma pequena biblioteca que lidou com meu caso de uso de querer métodos diferentes de origens diferentes bastante bem ... e menos fadiga de código para o próximo cara que a olha.
Kyle Baker

6
Obrigado, app.use(cors({origin: '*'}));trabalhou para mim, de acordo com enable-cors .
Danialk

2
Sugiro dar uma olhada na página npm cors para fazer melhor uso dela. Isso deixou as coisas muito claras para mim =).
13013SwagR

30

Outra maneira, é simplesmente adicionar os cabeçalhos à sua rota:

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
)de emoticon me confundiu
diEcho

17

A resposta principal funcionou bem para mim, exceto que eu precisava colocar mais de um domínio na lista de permissões.

Além disso, a resposta principal sofre com o fato de a OPTIONSsolicitação não ser tratada pelo middleware e você não a receber automaticamente.

Eu armazeno domínios allowed_originsna lista de permissões como na configuração do Express e coloco o domínio correto de acordo com o origincabeçalho, pois Access-Control-Allow-Originnão permite especificar mais de um domínio.

Aqui está o que eu acabei com:

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

É o mesmo 'if (app.get (' origens permitidas '). IndexOf (origin)! == - 1)?'?
Rune Jeppesen

13

O código de resposta permite apenas localhost: 8888. Este código não pode ser implantado na produção ou em um nome de servidor e porta diferente.

Para fazê-lo funcionar em todas as fontes, use isto:

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

2
Isso não funciona para mim! "* não é uma origem válida". Parece que o caractere * não é reconhecido como um curinga.
Francesco

Funciona para mim. ou seja, usando o curinga '*'. funciona tanto para chrome quanto safari.
AnBisw

Obrigado;) Funciona bem
Mauro

9

Instale a dependência de cors no seu projeto:

npm i --save cors

Adicione ao seu arquivo de configuração do servidor o seguinte:

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

Funciona para mim com a versão 2.8.4 cors.


"cors": "^2.8.5", "express": "^4.16.3",funciona bem apenas com a linha @monikaja sugerida. Obrigado!
RamiroIsBack

O que isso faz é permitir que todas as origens / domínios acessem o aplicativo, algo que você geralmente não deseja fazer. Em vez disso, especifique apenas os domínios permitidos.
Lacho Tomov

7

Isso funcionou para mim.

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

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

Você pode alterar * para atender às suas necessidades. Espero que isso possa ajudar.


7

Oi, isso acontece quando o front-end e o back-end estão sendo executados em portas diferentes. O navegador bloqueia as respostas do back-end devido à ausência nos cabeçalhos do CORS. A solução é fazer adicionar os cabeçalhos CORS na solicitação de back-end. A maneira mais fácil é usar o pacote cors npm.

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

Isso permitirá os cabeçalhos CORS em todas as suas solicitações. Para mais informações, consulte a documentação do 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();
    }


});

2

Adicione o seguinte código no app.js da API NODEJ Restful para evitar o erro "Access-Control-Allow-Origin" no angular 6 ou em qualquer outra estrutura

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

Você pode usar "$ http.jsonp"

OU

Abaixo está a solução alternativa para o chrome para testes locais

Você precisa abrir o chrome com o seguinte comando. (Pressione janela + R)

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

Nota: seu chrome não deve estar aberto. Quando você executa este comando, o chrome será aberto automaticamente.

Se você estiver inserindo esse comando no prompt de comando, selecione o diretório de instalação do chrome e use este comando.

Abaixo do código de script para o chrome aberto no MAC com "--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 &"

segundas opções

Você pode simplesmente usar o open (1) para adicionar os sinalizadores: open -a 'Google Chrome' --args --allow-file-access-from-files


Que tal no MAC ?? Chrome.exe - Permitir acesso a arquivos de arquivos
user1336103

/ Applications / Google \ Chrome.app/Contents/MacOS/Google \ Chrome - permite o acesso a arquivos de arquivos abrir o chrome, mas a mensagem ainda está mostrando "XMLHttpRequest não pode carregar o host local: 3000. Localhost de origem : 8888 é não permitido pelo Access-Control-Allow-Origin. "
user1336103 19/08/2013

+1 Posso confirmar que isso funciona com a opção Mac usando 'open'. Meu caso é um pouco diferente, pois estou simplesmente testando um site completamente baixado que acessa alguns arquivos JSON locais.
spong

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.