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);
Cara
fonte
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());
Michelle Tilley
fonte
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.

TonyTakeshi
fonte
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.

Zahid Rahman
fonte
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');
    });

}
Elmer
fonte
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.,

Jerome Anthony
fonte
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();
});
Dukegod
fonte
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.

Atyos
fonte
-6

Uma etapa adicional que precisei realizar foi mudar meu URL de http://localhostparahttp://127.0.0.0

user3795430
fonte
A que você se refere?
Blunderfest 01 de