Cómo habilitar el uso compartido de recursos de origen cruzado (CORS) en el marco express.js en node.js


101

Estoy tratando de construir un servidor web en node.js que admita secuencias de comandos entre dominios, al mismo tiempo que proporciona archivos estáticos desde un directorio público. Estoy usando express.js y no estoy realmente seguro de cómo permitir las secuencias de comandos entre dominios ( Access-Control-Allow-Origin: *).

Vi esta publicación , que no me resultó ú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 que app.all vs app.get. Es OPCIONES solicitar no OBTENER
Shimon Doodkin

consulte el servidor web local para ver un ejemplo de un servidor web estático de nodo simple que admite CORS
Lloyd

consulte enable-cors.org/server_apache.html para obtener más información
Mostafa

Respuestas:


159

Consulte el ejemplo de enable-cors.org :

En su aplicación ExpressJS en node.js, haga lo siguiente con sus rutas:

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

La primera llamada ( app.all) debe realizarse antes que todas las demás rutas en su aplicación (o al menos las que desea que estén habilitadas para CORS).

[Editar]

Si desea que los encabezados también se muestren para archivos estáticos, intente esto (asegúrese de que sea antes de la llamada a 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();
});

Probé esto con su código y obtuve los encabezados de los activos del publicdirectorio:

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

Por supuesto, podría empaquetar la función en un módulo para que pueda hacer 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());

Oye, gracias por tu respuesta. Hice lo que sugirió (primera parte, pero todavía no veo ninguna diferencia en los encabezados de solicitud). Adjunté mi código actual arriba. ¿Puede explicar cómo puedo integrar el resto de su solución a eso?
Guy

1
Me sorprende que, dado que está useusando app.routerantes express.static, no modifica los encabezados de los archivos estáticos; en cualquier caso, he actualizado mi respuesta para que funcione.
Michelle Tilley

¡Gracias! Veo que tienes razón. Los activos se obtienen del servidor con los encabezados solicitados. Puede que no haya sido claro sobre mi problema real. Estoy tratando de hacer una llamada API a un servidor externo con el comando get. y ahí es donde aparece el error: XMLHttpRequest no puede cargar SOMEURL.com . Origen localhost: 8888 no está permitido por Access-Control-Allow-Origin.
Guy

Puede que lo esté malinterpretando. ¿Tiene el control del servidor en SOMEURL.com?
Michelle Tilley

Lo siento, entiendo completamente tu respuesta ahora. Muchas gracias. Agradezco tu ayuda :)
Guy

58

Siguiendo la solución de @Michelle Tilley, aparentemente no funcionó para mí al principio. No estoy seguro de por qué, tal vez esté usando Chrome y una versión diferente de node. Después de algunos ajustes menores, ahora me está funcionando.

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

En caso de que alguien enfrente un problema similar al mío, esto podría ser útil.


Observe que app.all vs app.get. Es OPCIONES solicitar no OBTENER
Shimon Doodkin

Esto funciona para mí (estoy recuperando objetos usando Backbone). Estoy tratando de averiguar si funcionará en IE 8 ... parece que debería, pero no sé si se requiere algo especial para esta cosa "XDomainRequest" ... developer.mozilla.org/en- US / docs / HTTP /…
Adam Loving

ALGUNA INFORMACIÓN PARA FUTUROS USUARIOS: Estoy redirigiendo mi nombre de dominio a un repositorio de heroku, por lo que me encontré con este problema. De todos modos, la primera respuesta funcionó localmente, pero no después de que la empujé a heroku. Sin embargo, esta respuesta funcionó después de presionar a heroku.
Kris Hollenbeck

@KrisHollenbeck Esto no funciona para mí en heroku, ¿hiciste algo más?
Ben Craig

@BenCraig, No, pero en realidad dejó de funcionar para mí después del primer intento. Así que todavía tengo este problema.
Kris Hollenbeck

11

Pruebe estos módulos cors npm.

var cors = require('cors')

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

Este módulo proporciona muchas funciones para ajustar la configuración de cors, como la lista blanca de dominios, la habilitación de cors para apis específicas, etc.


2

Yo uso esto:

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 asume que sus controladores están ubicados en el directorio de controladores. cada archivo en este directorio debería ser algo como esto:

module.exports = function(app){

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

}

1

Recomiende usar el módulo cors express. Esto le permite incluir dominios en la lista blanca, permitir / restringir dominios específicamente a rutas, etc.


0

Debe configurar Access-Control-Allow-Credentials: true, si desea utilizar "cookies" a través de "Credenciales"

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

});

Agregue este código en su archivo index.js o server.js y cambie la matriz de origen permitida de acuerdo con sus requisitos.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.