Como ativar o compartilhamento de recursos de origem cruzada (CORS) na estrutura express.js em node.js


101

Estou tentando construir um servidor web em node.js que oferecerá suporte a scripts de domínio cruzado, enquanto ainda fornece arquivos estáticos de um diretório público. Estou usando o express.js e não tenho certeza de como permitir scripting entre domínios ( Access-Control-Allow-Origin: *).

Eu vi este post , que não achei útil.

var express = require('express')
  , app = express.createServer();

app.get('/', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
});

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(app.router);
});

app.configure('development', function () {

    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {


    var oneYear = 31557600000;
    //    app.use(express.static(__dirname + '/public', { maxAge: oneYear }));
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

Observe o app.all vs app.get. É pedido de OPÇÕES, não GET
Shimon Doodkin

consulte o servidor da web local para obter um exemplo de um nó simples, servidor da web estático que suporta CORS
Lloyd

consulte enable-cors.org/server_apache.html para mais informações
Mostafa

Respostas:


159

Confira o exemplo de enable-cors.org :

Em seu aplicativo ExpressJS em node.js, faça o seguinte com suas rotas:

app.all('/', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
 });

app.get('/', function(req, res, next) {
  // Handle the get for this route
});

app.post('/', function(req, res, next) {
 // Handle the post for this route
});

A primeira chamada ( app.all) deve ser feita antes de todas as outras rotas em seu aplicativo (ou pelo menos aquelas que você deseja habilitar para CORS).

[Editar]

Se você quiser que os cabeçalhos apareçam também para arquivos estáticos, tente fazer isso (certifique-se de que seja antes da chamada para use(express.static()):

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

Testei isso com o seu código e obtive os cabeçalhos dos recursos do publicdiretório:

var express = require('express')
  , app = express.createServer();

app.configure(function () {
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With");
      next();
    });
    app.use(app.router);
});

app.configure('development', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function () {
    app.use(express.static(__dirname + '/public'));
    app.use(express.errorHandler());
});

app.listen(8888);
console.log('express running at http://localhost:%d', 8888);

Você pode, é claro, empacotar a função em um módulo para fazer algo como

// cors.js

module.exports = function() {
  return function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    next();
  };
}

// server.js

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

Ei, obrigado pela sua resposta. Fiz o que você sugeriu (primeira parte, mas ainda não vejo nenhuma diferença nos cabeçalhos de solicitação) Anexei meu código atual acima. você pode explicar como posso integrar o resto da sua solução a isso?
Guy

1
Eu estou surpreso que, desde que você está useing app.routerantes express.staticque ele não modificar os cabeçalhos de arquivos estáticos; de qualquer forma, atualizei minha resposta para que funcione.
Michelle Tilley

Obrigado! Eu vejo que você está certo Os ativos são obtidos do servidor com os cabeçalhos solicitados. Posso não ter sido claro sobre meu verdadeiro problema. Estou tentando fazer uma chamada de API para um servidor externo com o comando get. e é aí que recebo o erro: XMLHttpRequest não pode carregar SOMEURL.com . Origem localhost: 8888 não é permitido pelo Access-Control-Allow-Origin.
Guy

Posso estar entendendo mal. Você controla o servidor em SOMEURL.com?
Michelle Tilley

Desculpe, eu entendo completamente sua resposta agora. Muito obrigado. Agradeço a sua ajuda :)
Guy

58

Seguindo a solução @Michelle Tilley, aparentemente não funcionou para mim no início. Não sei por que, talvez eu esteja usando o Chrome e uma versão diferente do nó. Depois de fazer alguns pequenos ajustes, agora está funcionando para mim.

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

No caso de alguém enfrentar um problema semelhante ao meu, isso pode ser útil.


Observe o app.all vs app.get. É pedido de OPÇÕES, não GET
Shimon Doodkin

Isso funciona para mim (estou buscando objetos usando o Backbone). Estou tentando descobrir se funcionará no IE 8 ... parece que deveria, mas não sei se algo especial é necessário para essa coisa de "XDomainRequest" ... developer.mozilla.org/en- US / docs / HTTP /…
Adam Loving

ALGUMAS INFORMAÇÕES PARA FUTUROS USUÁRIOS: Estou redirecionando meu nome de domínio para um repositório heroku, por isso estava tendo esse problema. De qualquer forma, a primeira resposta funcionou localmente, mas não depois que a empurrei para o heroku. No entanto, essa resposta funcionou após empurrar para heroku.
Kris Hollenbeck

@KrisHollenbeck Isso não funciona para mim no heroku, você fez mais alguma coisa?
Ben Craig

@BenCraig, Não, mas realmente parou de funcionar para mim após a primeira tentativa. Na verdade, ainda estou tendo esse problema.
Kris Hollenbeck

11

Tente este CORS módulos NPM.

var cors = require('cors')

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

Este módulo fornece muitos recursos para ajustar a configuração de cors, como lista de permissões de domínio, habilitando cors para apis específicos, etc.


2

Eu uso isso:

var app = express();

app
.use(function(req, res, next){
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With');
    next();
})
.options('*', function(req, res, next){
    res.end();
})
;

h.readFiles('controllers').forEach(function(file){
  require('./controllers/' + file)(app);
})
;

app.listen(port);
console.log('server listening on port ' + port);

este código assume que seus controladores estão localizados no diretório de controladores. cada arquivo neste diretório deve ser algo assim:

module.exports = function(app){

    app.get('/', function(req, res, next){
        res.end('hi');
    });

}

1

Recomende o uso do módulo cors express. Isso permite que você coloque domínios na lista de permissões, permita / restrinja domínios especificamente para rotas, etc.,


0

Você deve definir Access-Control-Allow-Credentials: true, se quiser usar "cookie" via "Credenciais"

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  next();
});

0
app.use(function(req, res, next) {
var allowedOrigins = [
  "http://localhost:4200"
];
var origin = req.headers.origin;
console.log(origin)
console.log(allowedOrigins.indexOf(origin) > -1)
// Website you wish to allow to
if (allowedOrigins.indexOf(origin) > -1) {
  res.setHeader("Access-Control-Allow-Origin", origin);
}

// res.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");

// 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,Authorization"
);

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

});

Adicione este código em seu arquivo index.js ou server.js e altere a matriz de origem permitida de acordo com sua necessidade.


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.