AWS Lambda-API-Gateway-Fehler "Fehlerhafte Lambda-Proxy-Antwort"


79

Ich versuche, mit AWS Lambda ein Hallo-Welt-Beispiel zu erstellen und es über das API-Gateway bereitzustellen. Ich klickte auf "Eine Lambda-Funktion erstellen", wodurch das API-Gateway eingerichtet und die Option "Leere Funktion" ausgewählt wurde. Ich habe die Lambda-Funktion hinzugefügt, die in der Anleitung zum Einstieg in das AWS-Gateway enthalten ist :

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

Das Problem ist, dass bei einer GET-Anfrage eine 502-Antwort zurückgegeben wird { "message": "Internal server error" }. In den Protokollen wird angezeigt, dass die Ausführung aufgrund eines Konfigurationsfehlers fehlgeschlagen ist: Fehlerhafte Lambda-Proxy-Antwort.

Antworten:


108

Wenn Sie sehen Malformed Lambda proxy response, bedeutet dies normalerweise, dass Ihre Antwort von Ihrer Lambda-Funktion nicht mit dem Format übereinstimmt, das API Gateway wie folgt erwartet

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

Wenn Sie die Lambda-Proxy-Integration nicht verwenden, können Sie sich bei der API-Gateway-Konsole anmelden und das Kontrollkästchen Lambda-Proxy-Integration deaktivieren.

Wenn Sie zeitweise auftreten Malformed Lambda proxy response, bedeutet dies möglicherweise, dass die Anforderung an Ihre Lambda-Funktion von Lambda gedrosselt wurde und Sie eine gleichzeitige Erhöhung des Ausführungslimits für die Lambda-Funktion anfordern müssen.




Diese Antwort war wirklich hilfreich. Vielen Dank!
Waleed93

48

Wenn Lambda als Proxy verwendet wird, sollte das Antwortformat sein

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

Hinweis: Der Körper sollte stringifiziert sein


Wenn "Antwort" der Name Ihres Objekts ist, funktioniert die Verwendung von JSON.stringify (Antwort) nicht. Es so zu lassen, hat für mich funktioniert. callback(null,response);
Neo

4
@Neo Sie müssen das Antwortobjekt nicht stringifizieren. Sie müssen die Daten innerhalb des Hauptschlüssels des
Antwortobjekts

Aus Neugier - warum muss der Körper gestrafft werden? Dies war mein Problem mit etwas, an dem ich gearbeitet habe, und es hat mich verwirrt - danke
andy mccullough

2
Von diesen ist nur statusCodeerforderlich, damit ein Aufruf von API Gateway erfolgreich ist.
Trenton

Es hat für mich funktioniert, sicherzustellen, dass der Körper streng ist. Vielen Dank +1
Kimutai

25

Ja, ich denke, das liegt daran, dass Sie dort keine richtige http-Antwort zurückgeben, weshalb Sie den Fehler erhalten.

persönlich benutze ich eine Reihe von Funktionen wie folgt:

    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.

Dann machst du einfach:

var responder = require('responder')

// some code

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

Wenn wir nun den Wert "Access-Control-Allow-Credentials" als "true" verwenden, können wir den Wert "Access-Control-Allow-Origin" nicht als "*"
beibehalten

1
Ich habe festgestellt, dass es nur einen Origin unterstützt: Header: {"Access-Control-Allow-Origin": "<< Single Domain >>", "Access-Control-Allow-Credentials": true // Erforderlich für Cookies, Autorisierungsheader mit HTTPS},
Santhosh Nagulanchi

6

Aus den AWS-Dokumenten

Rufen Sie in einer Lambda-Funktion in Node.js einen Rückruf auf, um eine erfolgreiche Antwort zurückzugeben (null, {"statusCode": 200, "body": "results"}). Um eine Ausnahme auszulösen, rufen Sie den Rückruf auf (neuer Fehler ('interner Serverfehler')). Für einen clientseitigen Fehler, z. B. wenn ein erforderlicher Parameter fehlt, können Sie einen Rückruf (null, {"statusCode": 400, "body": "Fehlende Parameter von ..."}) aufrufen, um den Fehler zurückzugeben, ohne einen auszulösen Ausnahme.


4

Für Python3:

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*'
        },
        'body': json.dumps({
            'success': True
        }),
        "isBase64Encoded": False
    }

Beachten Sie, dass das bodynicht festgelegt werden muss, sondern nur leer sein kann:

        'body': ''

3

Ein ganz besonderer Fall, wenn Sie die Header direkt übergeben, besteht die Möglichkeit, dass Sie diesen Header haben:

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

Aber Amazon braucht das:

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


3

Für alle anderen, die Probleme haben, wenn die Antwort gültig erscheint. Das funktioniert nicht:

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

aber das tut:

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

Es scheint auch, dass keine zusätzlichen Schlüssel auf dem Antwortobjekt vorhanden sein dürfen.


3

Wenn Sie Go mit https://github.com/aws/aws-lambda-go verwenden , müssen Sie verwenden events.APIGatewayProxyResponse.

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

3

Ich habe alle oben genannten Vorschläge ausprobiert, aber es funktioniert nicht, während der bodyWert nicht istString

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

3

Nur ein Stück Code für .net Core und C # :

using Amazon.Lambda.APIGatewayEvents;
...
var response = new APIGatewayProxyResponse
{
   StatusCode = (int)HttpStatusCode.OK,
   Body = JsonConvert.SerializeObject(new { msg = "Welcome to Belarus! :)" }),
   Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
return response;

Die Antwort von Lambda lautet:

{"statusCode":200,"headers":{"Content-Type":"application/json"},"multiValueHeaders":null,"body":"{\"msg\":\"Welcome to Belarus! :)\"}","isBase64Encoded":false}

Die Antwort vom API-Gateway lautet:

{"msg":"Welcome to Belarus! :)"}

1
OMG, vielen Dank, Sie haben mich gerade gerettet, nachdem Sie stundenlang versucht hatten, herauszufinden, wie man einen Header in der Antwort bekommt. Ich habe es mit einfachem JSON versucht, es hat nicht funktioniert. Ich habe Schlüsselwertpaare ausprobiert, aber nicht funktioniert. Wörterbuch war der richtige Weg! VIELEN DANK!
Mischa

1

Ich hatte diesen Fehler, weil ich versehentlich die Variable ServerlessExpressLambdaFunctionName aus der CloudFormation AWS :: Serverless :: Api-Ressource entfernt habe. Der Kontext hier ist https://github.com/awslabs/aws-serverless-express "Führen Sie serverlose Anwendungen und REST-APIs mit Ihrem vorhandenen Node.js-Anwendungsframework über AWS Lambda und Amazon API Gateway aus."


0

Falls das oben genannte für niemanden funktioniert, ist dieser Fehler aufgetreten, obwohl die Antwortvariable korrekt eingestellt wurde.

Ich habe in meiner Funktion eine RDS-Datenbank aufgerufen. Es stellte sich heraus, dass das Problem die Sicherheitsgruppenregeln (eingehend) in dieser Datenbank verursachte.

Sie möchten wahrscheinlich die IP-Adressen einschränken, die auf die API zugreifen können, aber wenn Sie möchten, dass sie schnell / schmutzig funktioniert, um zu testen, ob diese Änderung das Problem behebt, können Sie festlegen, dass sie alle so akzeptieren (Sie können auch die festlegen Bereich an den Ports, um auch alle Ports zu akzeptieren, aber das habe ich in diesem Beispiel nicht getan):

Geben Sie hier die Bildbeschreibung ein


0

Eine häufige Ursache für den Fehler "Fehlgebildete Lambda-Proxy-Antwort" ist, headersdass es sich nicht um {String: String, ...}Schlüssel / Wert-Paare handelt.

Da set-cookieHeader und im mehrfachen erscheinen, werden sie in http.request.callback.response als der dargestellten set-cookieSchlüssel ein mit Arrayder Strings anstelle eines Wertes EinzelString . Während dies für Entwickler funktioniert, versteht AWS API Gateway es nicht und gibt den Fehler "Fehlgebildete Lambda-Proxy-Antwort" aus.

Meine Lösung besteht darin, so etwas zu tun:

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

Beachten Sie, dass das ...oben Gesagte nicht Yada Yada Yada bedeutet . Es ist der ES6-Spread-Operator .


0

Hier ist ein anderer Ansatz. Konfigurieren Sie die Zuordnungsvorlage in Ihrer API-Gateway-Integrationsanforderung und -Antwort. Gehen Sie zu IntegrationRequest -> MappingTemplate -> wählen Sie "Wenn keine Vorlagen definiert sind" -> geben Sie application / json als Inhaltstyp ein. Dann müssen Sie keinen Json explizit senden. Sogar die Antwort, die Sie bei Ihrem Kunden erhalten, kann eine einfache Zeichenfolge sein.


0

Das Format Ihrer Funktionsantwort ist die Ursache für diesen Fehler. Damit API Gateway die Antwort einer Lambda-Funktion verarbeiten kann, muss die Antwort JSON in diesem Format sein:

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

Hier ist eine Beispielfunktion in Node.js mit der korrekt formatierten Antwort:

exports.handler = (Ereignis, Kontext, Rückruf) => {

var responseBody = {
    "key3": "value3",
    "key2": "value2",
    "key1": "value1"
};

var response = {
    "statusCode": 200,
    "headers": {
        "my_header": "my_value"
    },
    "body": JSON.stringify(responseBody),
    "isBase64Encoded": false
};
callback(null, response);

};

Ref: https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/


0

Python 3.7

Vor

{
    "isBase64Encoded": False,
    "statusCode": response.status_code,
    "headers": {
                  "Content-Type": "application/json",
               },
     "body": response.json()
}

Nach

{
    "isBase64Encoded": False,
    "statusCode": response.status_code,
    "headers": {
                  "Content-Type": "application/json",
               },
     "body": str(response.json()) //body must be of string type
}

0

Wenn Sie AWS noch nicht kennen und nur möchten, dass Ihre URL funktioniert,

Wenn Sie keinen Trigger für Ihre Lambda-Funktion erstellt haben, navigieren Sie zu der Funktion in der Lambda-Funktions-App und erstellen Sie einen Trigger, indem Sie API Gateway auswählen.

Navigieren Sie zu API Gateway App -> Wählen Sie das API-Gateway Ihres bestimmten Lambda aus (Methodenausführung) -> Klicken Sie auf INTEGRATION Request -> Deaktivieren Sie "Use Lambda Proxy Integration". .

Klicken Sie dann auf " <-Method Execution " und dann auf den Abschnitt Test Client. Geben Sie die Optionen ein und klicken Sie auf die Schaltfläche Test. Sie sollten eine Erfolgsantwort sehen.

Wenn Sie immer noch keine Erfolgsantwort erhalten können, erstellen Sie einen Alias ​​für die richtige Version (wenn die Lambda-Funktion mehrere Versionen enthält).

Wählen Sie die URL aus den Protokollen aus, verwenden Sie Ihr POST / GET-Tool (Postman) und wählen Sie die Authentifizierung als AWS-Signatur. Geben Sie Ihre Authentifizierungsschlüssel (AccessKey & SecretKey) in der Postman-Anfrage mit AWS Region & Service Name als Lambda an.

PS: Dies kann nur Anfängern helfen und für andere irrelevant sein.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.