Permitir la solicitud CORS REST a una aplicación Express/Node.js en Heroku

Escribí una API REST en el marco express para node.js que funciona para las solicitudes de la consola js en Chrome y la barra de URL, etc. Ahora estoy tratando de hacer que funcione para las solicitudes de otra aplicación, en una diferente dominio (CORS).

La primera solicitud, realizada automáticamente por el front-end de javascript, es para /api/search?uri=, y parece estar fallando en la solicitud de OPCIONES "preflight".

En mi aplicación Express, estoy agregando encabezados CORS, usando:

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

    // intercept OPTIONS method
    if ('OPTIONS' == req.method) {
      res.send(200);
    }
    else {
      next();
    }
};

y:

app.configure(function () {
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(allowCrossDomain);
  app.use(express.static(path.join(application_root, "public")));
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

Desde la consola de Chrome obtengo estos encabezados:

Request URL:http://furious-night-5419.herokuapp.com/api/search?uri=http%3A%2F%2Flocalhost%3A5000%2Fcollections%2F1%2Fdocuments%2F1

Método de solicitud: OPCIONES

Código de estado: 200 OK

Solicitar encabezados

Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, x-annotator-auth-token, accept
Access-Control-Request-Method:GET
Connection:keep-alive
Host:furious-night-5419.herokuapp.com
Origin:http://localhost:5000
Referer:http://localhost:5000/collections/1/documents/1
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5

Parámetros de cadena de consulta

uri:http://localhost:5000/collections/1/documents/1

Encabezados de respuesta

Allow:GET
Connection:keep-alive
Content-Length:3
Content-Type:text/html; charset=utf-8
X-Powered-By:Express

¿Parece esto una falta de encabezados adecuados enviados por la aplicación API?

Gracias.

preguntado el 12 de junio de 12 a las 18:06

Recibo este error en un código que no escribí, pero no entiendo la necesidad de un controlador para el OPTIONS método. ¿Podría alguien ayudarme a entender por qué no manejar solo el POST método en lugar de manejar ambos POST y OPTIONS ¿método? -

También podría querer incluir PATCH si lo usarás en lugar de PUT para actualizar un recurso -

6 Respuestas

Revisé su código en una aplicación ExpressJS limpia y funciona bien.

Intenta mover tu app.use(allowCrossDomain) a la parte superior de la función de configuración.

Respondido el 15 de junio de 12 a las 21:06

La razón por la que lo hizo es porque necesita tenerlo definido antes del app.use(app.router); ¡Salud! - Michael

En mi caso, el siguiente POST no se llama después de enviar res.send (200) cuando req.method == 'OPCIONES'. ¿Me estoy perdiendo algo más? - Aldo

2Aldo: Código necesario. ¿Puede ser que hayas olvidado algunos encabezados? Si su cliente no está enviando un POST después de que su servidor haya recibido correctamente una solicitud de OPCIONES de verificación previa, intente verificar la consola de herramientas del desarrollador. WebKit registra este tipo de errores en la consola del inspector web. - Olegas

@ConnorLeech Muy bien. Había estado haciendo el enfoque allowCrossDomain como se indicó anteriormente y estaba cansado de lidiar con todo ese encabezado mgmt. Además, dado que solo necesitábamos CORS para el desarrollo, no tenía sentido dedicar tantos ciclos para averiguar qué estaba pasando. Me alegro de que haya soporte para node.js para permitir esto fácilmente. - Steven

@ConnorLeech Creo que deberías agregar tu comentario como respuesta... funciona como una delicia, y es agradable y simple: cervecero

Estoy agregando esto como un https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be solo porque la publicación original se colocó como un comentario y, como tal, la pasó por alto la primera vez que revisé esta página.

Como @ConnorLeech señala en su comentario a la respuesta aceptada anterior, hay un paquete npm muy útil llamado, como era de esperar, cuernos. Su uso es tan simple como var cors = require('cors'); app.use(cors()); (nuevamente, copiado de la respuesta del Sr. Leech) y también se puede aplicar de una manera más estricta y configurable como se describe en su documentos.

También puede valer la pena señalar que el comentario original al que me refiero anteriormente se hizo en 2014. Ahora es 2019 y mirando el página de github del paquete npm el repositorio se actualizó hace tan solo nueve días.

Respondido el 06 de junio de 19 a las 03:06

para admitir cookies con Credenciales, necesita esta línea xhr.withCredentials = true;

mdn docs xhr.withCredentials

En Express Server, agregue este bloque antes que todos los demás

`app.all('*', function(req, res, next) {
     var origin = req.get('origin'); 
     res.header('Access-Control-Allow-Origin', origin);
     res.header("Access-Control-Allow-Headers", "X-Requested-With");
     res.header('Access-Control-Allow-Headers', 'Content-Type');
     next();
});`

Respondido el 15 de Septiembre de 16 a las 09:09

enter image description here

Siga los pasos a continuación:

npm instalar cors --save

Dentro de su archivo raíz js:

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

Respondido el 10 de Septiembre de 20 a las 21:09

No podría ser el caso para la mayoría de las personas que buscan esta pregunta, pero tuve exactamente el mismo problema y la solución no estaba relacionada con CORS.

Resulta que el secreto de JSON Web Token string no estaba definido en las variables de entorno, por lo que no se pudo firmar el token. Esto provocó a cualquier POST solicitud que se basa en verificar o firmar un token para obtener un tiempo de espera y devolver un 503 error, diciéndole al navegador que hay algo mal en CORS, que no lo es. Agregar la variable de entorno en Heroku resolvió el problema.

Espero que esto ayude a alguien.

Respondido 18 Jul 17, 01:07

Sí, ese era el problema conmigo. ¿Podría ser más específico sobre cómo resolvió el problema? Todavía estoy en desarrollo y ejecuto Express.js con el paquete cors de nodo. - Alan

@alan Estaba usando promesas para verificar el token en mi aplicación, de alguna manera si el secreto JWT no está definido, la promesa nunca se resolverá, aquí está el código Estaba usando si necesita más referencia. - GatoBrownie

Gracias por responder. Revisaré el código. Por secreto, asumo que estás hablando de la segunda clave privada. Estoy usando oauth2. - Alan

¡Agregaré que cualquier promesa fallida producirá este error engañoso! Tenía que ser explícito sobre el uso de una versión de Node o, de lo contrario, mis llamadas a la base de datos (mongo) simplemente se colgaban y lo único que el navegador podía decirme era 503 y luego algunas tonterías relacionadas con Cors. Este error realmente me confundió por más tiempo ya que tuve app.use(cors()); yendo. - alfanumérico0101

@CatBrownie, gracias por esta respuesta. ¡Exactamente lo que necesitaba! - Brunelli

El error de Cors podría ser un encubrimiento de su error real. Mire en los registros de su compilación heroku para ver su posible error real. El mío fue este.

Heroku Postgres: "psql: FATAL: no hay entrada pg_hba.conf para el host"

Respondido 22 Abr '21, 00:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.