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.