web-dev-qa-db-fra.com

Erreur de passerelle AWS lambda api "Réponse du proxy Lambda mal formé"

J'essaie de créer un exemple de bonjour le monde avec AWS lambda et de le servir via la passerelle api. J'ai cliqué sur "Créer une fonction Lambda", qui a configuré l'api gatway et sélectionné l'option Fonction vide. J'ai ajouté la fonction lambda présente dans Guide de démarrage rapide de la passerelle AWS

exports.handler = function(event, context, callback) {
  callback(null, {"Hello":"World"});  // SUCCESS with message
};

Le problème est que lorsque je lui adresse une requête GET, il renvoie une réponse 502 { "message": "Internal server error" }. Et les journaux indiquent "L’exécution a échoué en raison d’une erreur de configuration: réponse du proxy Lambda mal formée".

46
jjbskir

Habituellement, lorsque vous voyez Malformed Lambda proxy response, cela signifie que votre réponse de votre fonction Lambda ne correspond pas au format attendu par API Gateway, comme ceci

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "..."
}

Si vous n'utilisez pas l'intégration du proxy Lambda, vous pouvez vous connecter à la console API Gateway et désélectionner la case à cocher Intégration du proxy Lambda.

De même, si vous voyez un Malformed Lambda proxy response intermittent, cela peut vouloir dire que la requête de votre fonction Lambda a été limitée par Lambda et que vous devez demander une augmentation simultanée de la limite d'exécution de la fonction Lambda.

61
Ka Hou Ieong

Si lambda est utilisé comme proxy, le format de réponse doit être

{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}

Note: Le corps devrait être stratifié

31
selftaught91

Oui, alors je pense que c'est parce que vous ne renvoyez pas une réponse http appropriée, ce qui explique pourquoi vous obtenez l'erreur.

personnellement, j'utilise un ensemble de fonctions telles que:

    module.exports = {
        success: (result) => {
            return {
                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(result),
            }
        },
        internalServerError: (msg) => {
            return {
                statusCode: 500,
                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({
                    statusCode: 500,
                    error: 'Internal Server Error',
                    internalError: JSON.stringify(msg),
                }),
            }
        }
} // add more responses here.

Ensuite, vous faites simplement:

var responder = require('responder')

// some code

callback(null, responder.success({ message: 'hello world'}))
20
Mrk Fldig

À partir de AWS docs

Dans une fonction Lambda dans Node.js, appelez .__ pour obtenir une réponse satisfaisante. callback (null, {"statusCode": 200, "body": "résultats"}). Lancer un exception, call callback (nouvelle erreur ('erreur interne du serveur')). Pour un erreur côté client, par exemple, si un paramètre requis est manquant, vous pouvez appeler callback (null, {"statusCode": 400, "body": "paramètres manquants de ..."}) pour retourner l'erreur sans lever d'exception.

5
Jonathan

Un cas très très spécial, si vous passez directement les en-têtes, il y a une chance que vous ayez cet en-tête: 

"set-cookie": [ "........" ]

Mais Amazon a besoin de ceci:

"set-cookie": "[ \\"........\\" ]"

2
Miguel

Pour quiconque se débat lorsque la réponse semble valide. Cela ne fonctionne pas:

callback(null,JSON.stringify( {
  isBase64Encoded: false,
  statusCode: 200,
  headers: { 'headerName': 'headerValue' },
  body: 'hello world'
})

mais cela fait:

callback(null,JSON.stringify( {
  'isBase64Encoded': false,
  'statusCode': 200,
  'headers': { 'headerName': 'headerValue' },
  'body': 'hello world'
})

En outre, il semble qu'aucune clé supplémentaire ne soit autorisée sur l'objet de réponse.

2
Ciryon

J'ai eu cette erreur parce que j'ai accidentellement supprimé la variable ServerlessExpressLambdaFunctionName de la ressource CloudFormation AWS :: Serverless :: Api. Le contexte ici est https://github.com/awslabs/aws-serverless-express "Exécuter des applications sans serveur et des API REST à l'aide de votre infrastructure d'application Node.js existante, au-dessus de AWS Lambda et Amazon API Gateway "

1
Mark

Si vous utilisez Go avec https://github.com/aws/aws-lambda-go , vous devez utiliser events.APIGatewayProxyResponse

func hello(ctx context.Context, event ImageEditorEvent) (events.APIGatewayProxyResponse, error) {
    return events.APIGatewayProxyResponse{
        IsBase64Encoded: false,
        StatusCode:      200,
        Headers:         headers,
        Body:            body,
    }, nil
}
1
Kohei Mikami

J'ai essayé toutes les suggestions ci-dessus mais cela ne fonctionne pas alors que body valeur n'est pas String

return {
    statusCode: 200,
    headers: {
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": "*"
    },
    body: JSON.stringify({
        success: true
    }),
    isBase64Encoded: false
};
0
Long Nguyen

Une cause fréquente de l'erreur "Réponse incorrecte au proxy Lambda" est headers qui ne sont pas des paires clé {String: String, ...}.

Les en-têtes set-cookie pouvant apparaître et apparaissant en multiples, ils sont représentés dans http.request.callback.response sous la forme de la clé set-cookie ayant un Array SUR Strings valeur au lieu d'un single String. Bien que cela fonctionne pour les développeurs, AWS API Gateway ne le comprend pas et génère une erreur "Réponse incorrecte au proxy Lambda".

Ma solution est de faire quelque chose comme ça:

function createHeaders(headers) {
  const singleValueHeaders = {}
  const multiValueHeaders = {}
  Object.entries(headers).forEach(([key, value]) => {
    const targetHeaders = Array.isArray(value) ? multiValueHeaders : singleValueHeaders
    Object.assign(targetHeaders, { [key]: value })
  })

  return {
    headers: singleValueHeaders,
    multiValueHeaders,
  }
}

var output = {
  ...{
    "statusCode": response.statusCode,
    "body": responseString
  },
  ...createHeaders(response.headers)
}

Notez que le ... ci-dessus ne signifie pas Yada Yada Yada . C'est le opérateur de propagation ES6 .

0
Bruno Bronosky

Au cas où cela ne fonctionnerait pour personne, j’ai rencontré cette erreur malgré le réglage correct de la variable de réponse. 

J'étais en train d'appeler une base de données RDS dans ma fonction. Il s’est avéré que les règles du groupe de sécurité (entrant) sur cette base de données étaient à l’origine du problème. 

Vous voudrez probablement restreindre les adresses IP pouvant accéder à l'API, mais si vous voulez que cela fonctionne rapidement pour vérifier si cette modification le résout, vous pouvez le configurer pour qu'il accepte tous les utilisateurs similaires (vous pouvez également définir le paramètre sur les ports pour accepter tous les ports aussi, mais je ne l’ai pas fait dans cet exemple):

 enter image description here

0
abe732