API Gateway CORS: sin encabezado 'Access-Control-Allow-Origin'

103

Aunque CORS se ha configurado a través de API Gateway y el Access-Control-Allow-Originencabezado está configurado, sigo recibiendo el siguiente error cuando intento llamar a la API desde AJAX dentro de Chrome:

XMLHttpRequest no puede cargar http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY . No hay un encabezado 'Access-Control-Allow-Origin' presente en el recurso solicitado. Por lo tanto, no se permite el acceso al origen 'nulo'. La respuesta tenía el código de estado HTTP 403.

Intenté OBTENER la URL a través de Postman y muestra que el encabezado anterior se pasó correctamente:

Encabezados aprobados

Y de la respuesta de OPCIONES:

Encabezados de respuesta

¿Cómo puedo llamar a mi API desde el navegador sin volver a JSON-P?

Tyler
fuente
¿Lo tienes configurado en el S3? Si es así, ¿podría poner el Bucket Policy? Asegúrese de tener el método en su póliza
iSkore
10
El equipo de API Gateway aquí ... Si usa la función 'Habilitar CORS' en la consola, la configuración debería ser correcta. Mi mejor suposición sería que no está invocando la ruta de recurso correcta en su API en el JavaScript que está ejecutando el navegador. Si intenta realizar una llamada de API a un método / recurso / etapa inexistente, recibirá un 403 genérico sin ninguno de los encabezados CORS. No veo cómo el navegador podría perder el encabezado Access-Control-Allow-Origin si está llamando al recurso correcto ya que la llamada OPTIONS en Postman claramente contiene todos los encabezados CORS correctos.
jackko
1
@ RyanG-AWS, el cliente no está firmando la solicitud porque la API está autenticada por el recurso al que llama mediante un token específico del usuario, por lo que las credenciales no son un factor. Puedo llamar a la API visitando la URL directamente en el navegador y obtengo la respuesta adecuada.
Tyler
2
@makinbacon: ¿Encontraste una solución para esto? Estoy pasando por el mismo problema aquí.
Nirmal
1
Mis métodos y etapa fueron generados automáticamente por Lambda. Activé CORS después del hecho. Mismos errores que OP. Soplé las cosas generadas automáticamente, creé una nueva API y métodos, los implementé en una nueva etapa y funcionó bien.
escaldado

Respuestas:

118

Tengo el mismo problema. He utilizado 10 horas para averiguarlo.

https://serverless.com/framework/docs/providers/aws/events/apigateway/

// handler.js

'use strict';

module.exports.hello = function(event, context, callback) {

const response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
  },
  body: JSON.stringify({ "message": "Hello World!" })
};

callback(null, response);
};
Riseres
fuente
También se solucionó el problema que estaba teniendo. ¡Gracias por su respuesta!
Eric Brown
No uso servidores sin servidor, pero esto resolvió mi problema. Supongo que necesitas pasar esos encabezados desde la fuente real.
Costa
2
Para su información, hay un problema con el ejemplo que se presenta aquí. Si tiene "Access-Control-Allow-Credentials": verdadero, no puede tener el comodín * para Access-Control-Allow-Origin. Esta regla la aplica el navegador. Vea aquí y aquí
Kevin
1
Esto no funciona. Nuevamente muestra el mismo error. El campo de encabezado de solicitud access-control-allow-credentials no está permitido por Access-Control-Allow-Headers en la respuesta de verificación previa.
mitesh7172
1
Para cualquier persona curiosa, aquí están los documentos oficiales que mencionan esto: docs.aws.amazon.com/apigateway/latest/developerguide/… > Para integraciones de proxy Lambda o HTTP, aún puede configurar los encabezados de respuesta necesarios> OPCIONES en API Gateway. Sin embargo, debe confiar en el> back-end para devolver los encabezados Access-Control-Allow-Origin porque la> respuesta de integración está deshabilitada para la integración del proxy.
Leonid Usov
104

Si alguien más se encuentra con esto todavía, pude rastrear la causa raíz en mi aplicación.

Si está ejecutando API-Gateway con autorizadores personalizados, API-Gateway enviará un 401 o 403 antes de que llegue a su servidor. De forma predeterminada, API-Gateway NO está configurado para CORS cuando se devuelve 4xx desde un autorizador personalizado.

También - si quieres pasar a estar recibiendo un código de estado 0o 1de una petición que corre a través de la API de puerta de enlace, esto es probablemente su problema.

Para solucionarlo, en la configuración de API Gateway, vaya a "Respuestas de Gateway", expanda "Default 4XX" y agregue un encabezado de configuración CORS allí. es decir

Access-Control-Allow-Origin: '*'

Asegúrese de volver a implementar su puerta de enlace , ¡y listo!

Gabriel Doty
fuente
7
te quiero. estado trabajando seriamente en esto durante dos días.
efong5
4
Para aquellos que quieran hacer esto con la AWS CLI, use:aws apigateway update-gateway-response --rest-api-id "XXXXXXXXX" --response-type "DEFAULT_4XX" --patch-operations op="add",path="/responseParameters/gatewayresponse.header.Access-Control-Allow-Origin",value='"'"'*'"'"'
Will
1
No estoy usando autorizadores personalizados y aún lo necesito, ya que mi solicitud tenía un JSON incorrecto, ¡gracias!
Force Hero
9
nota para mí: no olvides implementar la API después :)
danieln
2
Extraño, esto funcionó para mí, pero no tuve que reubicarme. Intenté volver a implementarlo antes. No estoy seguro de por qué funcionó para mí.
Michael
19

1) Necesitaba hacer lo mismo que @riseres y algunos otros cambios. Estos son mis encabezados de respuesta:

headers: {
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Credentials' : true,
            'Content-Type': 'application/json'
        }

2) Y

Según esta documentación:

http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

Cuando usa proxy para funciones lambda en la configuración de API Gateway, los métodos post u get no tienen encabezados agregados, solo las opciones. Debe hacerlo manualmente en la respuesta (servidor o respuesta lambda).

3) Y

Además de eso, necesitaba deshabilitar la opción 'Se requiere clave API' en mi método de publicación de puerta de enlace API.

Carlos Alberto Schneider
fuente
5
Sí, creo que lo sutil que muchos de nosotros extrañamos inicialmente es que una vez que configure su integración de API Gateway para la función Lambda con "Use Lambda Proxy Integration", entonces debe hacer lo que usted y otros dicen y asegurarse de que se agreguen los encabezados. programáticamente en la respuesta de su lambda. El material de autogeneración que se crea al "Habilitar CORS" en una puerta de enlace de API y crear un respondedor de OPCIONES es excelente, pero no lo lleva hasta allí si establece "Usar integración de proxy de Lambda" en la Solicitud de integración dentro de la API Puerta.
1
Esto funcionó para mí ... después de leer el manual correctamente: Importante Al aplicar las instrucciones anteriores al método ANY en una integración de proxy, no se establecerán los encabezados CORS aplicables. En cambio, su backend debe devolver los encabezados CORS aplicables, como Access-Control-Allow-Origin. docs.aws.amazon.com/apigateway/latest/developerguide/…
BennyHilarante
14

Si ha intentado todo lo relacionado con este tema sin éxito, terminará donde lo hice. Resulta que las instrucciones de configuración de CORS existentes de Amazon funcionan bien ... ¡solo asegúrese de recordar volver a implementar ! El asistente de edición CORS, incluso con todas sus pequeñas y agradables marcas de verificación verdes, no realiza actualizaciones en vivo de su API. Quizás obvio, pero me dejó perplejo durante medio día.

ingrese la descripción de la imagen aquí

lase
fuente
Esto fue. Literalmente trabajando en esto durante dos días. No estoy seguro de que la lógica no al menos solicite una nueva implementación después de editar la puerta de enlace.
Chris Christensen
@ChrisChristensen me alegro de que lo hayas resuelto; siempre hay algo tan aliviado pero increíblemente derrotador sobre problemas como este
lase
Esta es la respuesta que es válida en 2020. Gracias
Rahul Khanna
RE-IMPLEMENTAR RE-DPLOY RE-
DESPLEGAR
11

Conseguí que mi ejemplo funcionara: acabo de insertar 'Access-Control-Allow-Origin': '*', dentro de los encabezados: {} en la función Lambda de nodejs generada. Hice no hay cambios en la capa API generada-Lambda.

Aquí está mi NodeJS:

'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
    const done = ( err, res ) => callback( null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers:{ 'Access-Control-Allow-Origin' : '*' },
    });
    switch( event.httpMethod ) {
        ...
    }
};

Aquí está mi llamada AJAX

$.ajax({
    url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
    type: 'GET',
    beforeSend: function(){ $( '#loader' ).show();},
    success: function( res ) { alert( JSON.stringify(res) ); },
    error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
    complete:function(){ $('#loader').hide(); }
});
MannyC
fuente
He encontrado que mucha documentación de Amazon está desactualizada, incluso con el fragmento de ruta "../latest/ ..". Después de descartar todo hace aproximadamente una semana, el botón CORS de repente indicó que funciona correctamente. La API creó el método "CUALQUIER" automáticamente y el botón CORS creó el método "OPCIONES" automáticamente; no agregué nada a la API. El "GET" anterior funciona y desde entonces agregué un "POST" ajax que también funciona sin que yo toque la API.
MannyC
Pasé casi dos horas tratando de averiguar cómo agregar Access-Control-Allow-Origin a la respuesta del método usando la consola de AWS, pero esto también fue lo único que funcionó para mí.
Shn_Android_Dev
8

Para los empleados de Google:

He aquí por qué:

  • Solicitud simple, o GET/ POSTsin cookies no activa la verificación previa
  • Cuando configura CORS para una ruta, API Gateway solo creará un OPTIONSmétodo para esa ruta, luego enviará Allow-Originencabezados usando respuestas simuladas cuando el usuario llame OPTIONS, pero GET/ POSTno obtendrá Allow-Originautomáticamente
  • Si intenta enviar solicitudes simples con el modo CORS activado, obtendrá un error porque esa respuesta no tiene Allow-Originencabezado
  • Puede adherirse a las mejores prácticas, las solicitudes simples no están destinadas a enviar una respuesta al usuario, enviar autenticación / cookies junto con sus solicitudes para que sea "no simple" y se activará la verificación previa.
  • Aún así, tendrá que enviar los encabezados CORS usted mismo para la siguiente solicitud OPTIONS

Para resumirlo:

  • OPTIONSAPI Gateway solo generará inofensivo
  • OPTIONSsolo se utilizan por el navegador como medida de precaución para comprobar la posibilidad de CORS en una ruta
  • La aceptación de CORS dependerá del método real, p GET. Ej .POST
  • Tienes que enviar manualmente los encabezados apropiados en tu respuesta
theaws.blog
fuente
6

Acabo de agregar encabezados a la respuesta de mi función lambda y funcionó como un encanto

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hey it works'),
        headers:{ 'Access-Control-Allow-Origin' : '*' }
    };
    return response;
};
Vishal Shetty
fuente
4

Encontré una solución simple dentro

API Gateway> Seleccione su punto final de API> Seleccione el método (en mi caso fue el POST)

Ahora hay un menú desplegable ACCIONES> Habilitar CORS ... selecciónelo.

Ahora seleccione el menú desplegable ACCIONES nuevamente> Implementar API (volver a implementarlo)

ingrese la descripción de la imagen aquí

Funcionó !

Ravi Ram
fuente
¿Por qué se ha rechazado esta respuesta, pero hay otras respuestas similares a continuación?
Dinesh Kumar
Para la invocación de la puerta de enlace API basada en AWS, esta solución funciona
ewalel
3

Hice que el mío funcionara después de darme cuenta de que el autorizador lambda estaba fallando y, por alguna razón desconocida, se estaba traduciendo en un error CORS. Una solución simple a mi autorizador (y algunas pruebas de autorizador que debería haber agregado en primer lugar) y funcionó. Para mí, la acción de API Gateway 'Habilitar CORS' era necesaria. Esto agregó todos los encabezados y otras configuraciones que necesitaba en mi API.

RodP
fuente
y volver a implementar! :)
Robin C Samuel
3

Para mí, la respuesta que FINALMENTE FUNCIONÓ, fue el comentario de James Shapiro de la respuesta de Alex R (el segundo más votado). Me metí en este problema de API Gateway en primer lugar, al intentar obtener una página web estática alojada en S3 para usar lambda para procesar la página de contacto y enviar un correo electrónico. Simplemente marcando [] Default 4XX solucionó el mensaje de error.

ingrese la descripción de la imagen aquí

Jason
fuente
¿Dónde encuentras este menú? No lo veo por ningún lado.
Nick H
@NickH echa un vistazo a la foto de Ravi Ram. En "Acciones", debería haber un elemento llamado "Habilitar CORS" y cuando lo seleccione, aparecerá el menú.
Jason
2

Después de cambiar su función o código, siga estos dos pasos.

Primero habilite CORS y luego implemente API cada vez.

Ankit Kumar Rajpoot
fuente
Gracias por eso. No noté el "Habilitar CORS" en el recurso. Me hizo perder la cabeza.
Shlomi Bazel
2

Implementar el código después de habilitar CORS para ambos POSTy OPTIONSfuncionó para mí.

Ziaur Rahman
fuente
1
Gracias por su contribución, sin embargo, ¿puede explicar por qué funcionó para usted? Te invito a leer esta guía para mejorar tu respuesta: "Cómo escribo una buena respuesta" aquí: stackoverflow.com/help/how-to-answer
Guillaume Raymond
1

Estoy corriendo aws-serverless-express, y en mi caso necesitaba editar simple-proxy-api.yaml.

Antes de que se configurara CORS https://example.com, simplemente cambié el nombre de mi sitio y lo volví a implementar a través de npm run setup, y actualicé mi lambda / pila existente.

#...
/:
#...
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
/{proxy+}:
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
James L.
fuente
1

En mi caso, dado que estaba usando AWS_IAM como el método de autorización para API Gateway, necesitaba otorgar mis permisos de rol de IAM para llegar al punto final.

CamHart
fuente
2
Hombre, me alegro de haber dejado este comentario. Esto me sigue sucediendo: D.
CamHart
Me encanta encontrar mi propia solución a un problema recurrente en el futuro.
Zac Grierson
0

Otra causa raíz de este problema podría ser una diferencia entre HTTP / 1.1 y HTTP / 2.

Síntoma: algunos usuarios, no todos, informaron que obtenían un error CORS al usar nuestro software.

Problema: La Access-Control-Allow-Origincabecera faltaba veces .

Contexto: teníamos una Lambda en su lugar, dedicada a manejar OPTIONSsolicitudes y responder con los encabezados CORS correspondientes, como hacer Access-Control-Allow-Origincoincidir una lista blanca Origin.

Solución: API Gateway parece transformar todos los encabezados a minúsculas para las llamadas HTTP / 2, pero mantiene las mayúsculas para HTTP / 1.1. Esto provocó event.headers.originque fallara el acceso a .

Compruebe si también tiene este problema:

Suponiendo que su API está ubicada en https://api.example.com, y su interfaz está en https://www.example.com. Usando CURL, haga una solicitud usando HTTP / 2:

curl -v -X OPTIONS -H 'Origin: https://www.example.com' https://api.example.com

La salida de respuesta debe incluir el encabezado:

< Access-Control-Allow-Origin: https://www.example.com

Repita el mismo paso usando HTTP / 1.1 (o con un Originencabezado en minúsculas ):

curl -v -X OPTIONS --http1.1 -H 'Origin: https://www.example.com' https://api.example.com

Si Access-Control-Allow-Originfalta el encabezado, es posible que desee verificar la distinción entre mayúsculas y minúsculas al leer el Originencabezado.

Michael Seibt
fuente
0

Además de otros comentarios, algo a tener en cuenta es el estado devuelto por su integración subyacente y si se devuelve el encabezado Access-Control-Allow-Origin para ese estado.

Hacer lo 'Habilitar CORS' solo configura el estado 200. Si tiene otros en el punto final, por ejemplo, 4xx y 5xx, debe agregar el encabezado usted mismo.

Nigel Atkinson
fuente
-2

En mi caso, simplemente estaba escribiendo mal la URL de la solicitud de recuperación. Activado serverless.yml, lo configura corsen true:

register-downloadable-client:
    handler: fetch-downloadable-client-data/register.register
    events:
      - http:
          path: register-downloadable-client
          method: post
          integration: lambda
          cors: true
          stage: ${self:custom.stage}

y luego, en el controlador lambda, envía los encabezados, pero si realiza la solicitud de recuperación incorrecta en la interfaz, no obtendrá ese encabezado en la respuesta y obtendrá este error. Por lo tanto, vuelva a verificar la URL de su solicitud en el frente.

Ericson Willians
fuente
-3

En Python puede hacerlo como en el siguiente código:

{ "statusCode" : 200,
'headers': 
    {'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': "*"
     },
"body": json.dumps(
    {
    "temperature" : tempArray,
    "time": timeArray
    })
 }
Mukesh Arya
fuente