web-dev-qa-db-fra.com

AWS API Gateway - CORS + POST ne fonctionne pas

CORSme rend vraiment fou et je suis vraiment à court d'idées quant à quoi essayer de le faire fonctionner.

J'ai créé un Api Api simple avec 1 ressource appelée 'abc' et ajouté 2 méthodes GET et POST, avec Authorization défini sur NONE et API Key Obligatoire défini sur false, tout est déployé à une étape appelée «dev».

Bien sûr, j'ai activéCORSsur les deux méthodes et je vois les 3 en-têtes Contrôle d'accès-Autoriser-Origine , Accès-Contrôle-Autoriser-en-têtes et Accès-Contrôle- Allow-Methods ajouté à la méthode OPTIONS et à/ Access-Control-Allow-Origin ajouté aux méthodes POST et GET.

Les deux appels sont mappés vers la même fonction lambda qui envoie simplement un texte 'Hello from Lambda' à la console.

Ensuite, j'ai créé une simple page HTML hébergée en tant que site Web statique sur S3 , lui ai indiqué un domaine à l'aide de Route53 et j'ai commencé à tester l'API à l'aide de jQuery $ .ajax faire les appels.

Tout semble facile, simple et exactement comme expliqué dans la documentation, sauf que seul le GET fonctionne et affiche le texte dans la console comme prévu. La version POST génère l'erreur suivante: 

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access. The response had HTTP status code 400.

L'appel de contrôle en amont fonctionne et renvoie 200 OK et tous les en-têtes sont présents, mais l'appel POST renvoie l'erreur et une demande 400 demandes erronées.

S'il vous plaît, toute aide est vraiment appréciée, j'espère que l'équipe AWS regarde aussi ...

Merci les gars. 


EDITED - Copié à partir de Google Chrome:

En-têtes de demande brute POST:

POST /dev/urls HTTP/1.1
Host: kykul1mshe.execute-api.us-east-1.amazonaws.com
Connection: keep-alive
Content-Length: 73
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/json
Referer: http://example.com/dev.html
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

En-têtes de réponse brute POST:

HTTP/1.1 400 Bad Request
Date: Fri, 19 Aug 2016 02:14:16 GMT
Content-Type: application/json
Content-Length: 177
Connection: keep-alive
x-amzn-RequestId: a1160e45-65b2-11e6-9766-cd61e49fbcdb
X-Cache: Error from cloudfront
Via: 1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id: N9mf7apicKbSM_MiZjePbEgZGIFKckWJ3lZljH8iHVKFVTcIIOQuHg==

Cela retourne 400 Bad Request

OPTIONS En-têtes de demande brute:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:kykul1mshe.execute-api.us-east-1.amazonaws.com
Origin:http://example.com
Referer:http://example.com/dev.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36

OPTIONS En-têtes de réponse brutes:

Access-Control-Allow-Headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,Cache-Control,X-Requested-With
Access-Control-Allow-Methods:POST,OPTIONS
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:79
Content-Type:application/json
Date:Fri, 19 Aug 2016 02:14:16 GMT
Via:1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id:KpGEDmIuf5RHcUnBWuA3oEMZgWHwrjy3SpLuOflRhAD8IIx5vyKGSw==
x-amzn-RequestId:a10bae11-65b2-11e6-bcf7-63b49c24629e
X-Cache:Miss from cloudfront

Cela retourne 200 OK

15
HBR

Ok, j’ai trouvé l’origine du problème, qui n’est absolument pas lié à APIG, et confirme ce que @AbhignaNagaraja a mentionné, à savoir que mon APIG était correctement configuré.

Le problème est en fait dans la façon dont j'ai appelé jQuery.ajax, que je pensais être assez intelligent pour convertir mes paramètres en chaîne JSON lorsque contentType est 'application/json'. Il semble que j’ai dû stringifier manuellement les paramètres JSON au lieu de passer un JSON et d’avoir jQuery pour le stringifier.

C'est donc le mauvais appel:

$.ajax({
        url: myEndpoint,
        type: 'POST',
        crossDomain: true,
        data: {
            url: $('#url').val()
        },
        headers: {
            "X-Api-Key": 'blablabla'
        },
        dataType: 'json',
        contentType: "application/json",
        success: function (data) {
            console.info(data);
        }
    });

Et c'est le bon appel:

 $.ajax({
        url: myEndpoint,
        type: 'POST',
        crossDomain: true,
        data: JSON.stringify({
            url: $('#url').val()
        }),
        headers: {
            "X-Api-Key": 'blablabla'
        },
        dataType: 'json',
        contentType: "application/json",
        success: function (data) {
            console.info(data);
        }
    });

Cela peut être un indice si vous corrigez un tel problème avec CORS: téléchargez simplement le kit SDK AWS APIG et essayez d'exécuter l'appel en utilisant l'apigClient fourni par AWS et comparez les en-têtes avec ceux que vous obtenez avec votre client personnalisé. les 2 ensembles d'en-têtes que j'ai obtenus avec jQuery et apigClient, j'ai remarqué que Request Payload était différent et que j'ai réalisé que le format était incorrect, puis le 400 code et le Non 'Access-Control-Allow-Origin' en-tête est présent tout sens.

J'espère que ça aide.

14
HBR

J'ai eu un problème similaire, mais avec l'intégration du proxy lambda:

  • CORS activé sur AWS API Gateway à l'aide du navigateur

  • intégration lambda-proxy activée

Lorsque vous utilisez l'intégration de proxy lambda, vous pouvez renvoyer des en-têtes personnalisés à partir du code de la lambda:

        var result = {
        statusCode: data.statusCode | 200,
        headers: {
          "Access-Control-Allow-Origin": "*"
        },
        body: JSON.stringify(responseBody)
    };
    callback(null, result);

De cette façon, vous obtiendrez l’en-tête CORS .. Je pense qu’il pourrait exister un meilleur moyen de le faire fonctionner avec l’intégration proxy lambda sans coupler la CORS dans le code du lambda, merci de me le faire savoir.

9
arseneoaa

J'ai eu un problème similaire - et cela n'avait rien à voir avec la façon dont l'API a été configurée ou la demande POST que je faisais au niveau du serveur frontal. Ce qui a résolu le problème pour moi, c'est le déploiement de l'API sur AWS API Gateway. Une fois que vous avez créé une méthode/ressource API et que vous les avez liées à une fonction lambda, elles ne se déploient pas automatiquement.

Vous devez cliquer sur "Actions" puis sur "Déployer l'API" pour accéder à ces MicroServices à partir du serveur frontal.

3
Marquistador

pour résoudre ce problème, je vous présente ma configuration de la configuration de poste dans apy gateway

Méthode d'option - Réponse d’intégration - Cartographie des en-têtes

X-Requested-With '*'
Access-Control-Allow-Headers 'Content-Type,x-requested-with,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods'
Access-Control-Allow-Origin 'http://localhost:4200'
Access-Control-Allow-Methods 'POST,OPTIONS'

Post-méthode - Réponse d'intégration - Mappage des en-têtes

Access-Control-Allow-Origin "*" ---> can be changed by your ip obviously

J'espère que ceci vous aide

2
Andres Navarro

De nombreux articles vous demandent de vous assurer que la fonction lambda renvoie les en-têtes CORS appropriés, et qu'ils sont corrects. Cependant, c’est égalementcriticalque l’objet json est stringifié à l’aide de JSON.stringify (). Il semble que Postman le fasse pour nous. Il est donc trompeur que la requête Postman et la requête $ .ajax envoient le même objet json; pourtant on réussit et on échoue.

0
rickfarina

Si vous utilisez l'intégration de proxy dans API Gateway, l'activation de CORS à partir d'API Gateway ne fonctionne pas. Vous devez définir l'en-tête 'Access-Control-Allow-Origin' à partir de votre code Lambda même.

Son mentionné dans doc .

Exemple de code Python:

    response = {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Origin': '*'
        },
        'body': json.dumps({'message': 'CORS enabled')
    }
    return response
0
Dawn T Cherian