Comment activer le partage de ressources croisées (CORS) dans le cadre express.js sur node.js

101

J'essaie de créer un serveur Web dans node.js qui prendra en charge les scripts inter-domaines, tout en fournissant des fichiers statiques à partir d'un répertoire public. J'utilise express.js et je ne sais pas vraiment comment autoriser les scripts interdomaines ( Access-Control-Allow-Origin: *).

J'ai vu ce post , que je n'ai pas trouvé utile.

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);
Gars
la source
Notez l'app.all vs app.get. C'est OPTIONS demande pas GET
Shimon Doodkin
voir local-web-server pour un exemple d'un simple nœud, serveur web statique qui prend en charge CORS
Lloyd
voir enable-cors.org/server_apache.html pour plus d'informations
Mostafa
"Access-Control-Allow-Origin", "*"rend votre API intéressante pour les applications de phishing. Envisagez de n'autoriser que les origines connues.
Martin Schneider

Réponses:

159

Consultez l'exemple de enable-cors.org :

Dans votre application ExpressJS sur node.js, procédez comme suit avec vos itinéraires:

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

Le premier appel ( app.all) doit être effectué avant toutes les autres routes de votre application (ou du moins celles que vous souhaitez activer CORS).

[Éditer]

Si vous souhaitez que les en-têtes s'affichent également pour les fichiers statiques, essayez ceci (assurez-vous que c'est avant l'appel à 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();
});

J'ai testé cela avec votre code et j'ai obtenu les en-têtes sur les actifs du publicrépertoire:

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

Vous pouvez, bien sûr, intégrer la fonction dans un module afin de pouvoir faire quelque chose comme

// 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
la source
Hé, merci pour votre réponse. J'ai fait ce que vous avez suggéré (première partie, mais je ne vois toujours pas de différence dans les en-têtes de demande), j'ai joint mon code actuel ci-dessus. pouvez-vous expliquer comment je peux intégrer le reste de votre solution à cela?
Guy
1
Je suis surpris que, puisque vous êtes useing app.routeravant express.staticqu'il ne modifie pas les en- têtes des fichiers statiques; dans tous les cas, j'ai mis à jour ma réponse pour qu'elle fonctionne.
Michelle Tilley
Merci! Je vois que tu as raison. Les ressources obtenues du serveur sont avec les en-têtes demandés. Je n'ai peut-être pas été clair sur mon vrai problème. J'essaie de faire un appel API à un serveur externe avec la commande get. et c'est là que j'obtiens l'erreur: XMLHttpRequest ne peut pas charger SOMEURL.com . L' hôte local d' origine : 8888 n'est pas autorisé par Access-Control-Allow-Origin.
Guy
J'ai peut-être un malentendu. Contrôlez-vous le serveur de SOMEURL.com?
Michelle Tilley
Désolée, je comprends parfaitement votre réponse maintenant. Merci beaucoup. J'apprécie votre aide :)
Guy
58

Suite à la solution @Michelle Tilley, apparemment cela n'a pas fonctionné pour moi au début. Je ne sais pas pourquoi, j'utilise peut-être chrome et une version différente de node. Après quelques modifications mineures, cela fonctionne pour moi maintenant.

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

Au cas où quelqu'un serait confronté à un problème similaire au mien, cela pourrait être utile.

TonyTakeshi
la source
Notez l'app.all vs app.get. C'est OPTIONS demande pas GET
Shimon Doodkin
Cela fonctionne pour moi (je récupère des objets en utilisant Backbone). J'essaie de savoir si cela fonctionnera dans IE 8 ... ça devrait être le cas, mais je ne sais pas si quelque chose de spécial est nécessaire pour cette chose "XDomainRequest" ... developer.mozilla.org/en- US / docs / HTTP /…
Adam Loving
QUELQUES INFORMATIONS POUR LES UTILISATEURS FUTURS: Je redirige mon nom de domaine vers un repo heroku, c'est pourquoi je rencontrais ce problème. Quoi qu'il en soit, la première réponse a fonctionné localement, mais pas après l'avoir poussée vers heroku. Cependant, cette réponse a fonctionné après avoir poussé à heroku.
Kris Hollenbeck
@KrisHollenbeck Cela ne fonctionne pas pour moi sur heroku, avez-vous fait autre chose?
Ben Craig
@BenCraig, non, mais cela a en fait cessé de fonctionner pour moi après le premier essai. J'ai donc toujours ce problème.
Kris Hollenbeck
11

Essayez ces modules cors npm.

var cors = require('cors')

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

Ce module fournit de nombreuses fonctionnalités pour affiner le réglage des cors tels que la liste blanche de domaine, l'activation des cors pour des API spécifiques, etc.

Zahid Rahman
la source
2

J'utilise ceci:

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

ce code suppose que vos contrôleurs se trouvent dans le répertoire des contrôleurs. chaque fichier de ce répertoire devrait ressembler à ceci:

module.exports = function(app){

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

}
Elmer
la source
1

Recommander d'utiliser le module cors express. Cela vous permet de mettre des domaines sur liste blanche, d'autoriser / restreindre des domaines spécifiquement aux itinéraires, etc.,

Jérôme Anthony
la source
0

Vous devez définir Access-Control-Allow-Credentials: true, si vous souhaitez utiliser "cookie" via "Credentials"

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
la source
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();

});

Ajoutez ce code dans votre fichier index.js ou server.js et modifiez le tableau d'origine autorisé en fonction de vos besoins.

Atyos
la source
-6

Un I étape supplémentaire nécessaire pour prendre devais changer mon URL de http://localhostlahttp://127.0.0.0

user3795430
la source
A quoi faites-vous référence?
Blunderfest