Подтвердить что ты не робот

Есть ли способ изменить коды статуса http, возвращаемые шлюзом API Amazon?

Например, если я хочу вернуть определенную ошибку 400 для недопустимых параметров или, возможно, 201, когда вызов лямбда-функции привел к созданию.

Мне бы хотелось иметь разные коды статуса http, но похоже, что api gateway всегда возвращает код состояния 200, даже если функция лямбда возвращает ошибку.

4b9b3361

Ответ 1

Обновление за 20-9-2016

Amazon, наконец, упростил использование интеграции Lambda Proxy. Это позволяет вашей функции Lambda возвращать правильные HTTP-коды и заголовки:

let response = {
    statusCode: '400',
    body: JSON.stringify({ error: 'you messed up!' }),
    headers: {
        'Content-Type': 'application/json',
    }
};

context.succeed(response);

Произнесите прощальное отображение запроса/ответа в интерфейсе API!

Вариант 2

Интегрируйте существующее приложение Express со шлюзом Lambda/API с помощью aws-serverless-express.

Ответ 2

Здесь самый быстрый способ возврата пользовательских кодов состояния HTTP и пользовательский errorMessage:

В панели инструментов API Gateway выполните следующие действия:

  • В методе вашего ресурса нажмите на ответ метода
  • В таблице "Состояние HTTP" нажмите "Добавить ответ" и добавьте в каждый код состояния HTTP, который вы хотели бы использовать.
  • В методе вашего ресурса нажмите на запрос интеграции
  • Добавьте ответ интеграции для каждого из кодов состояния HTTP, которые вы создали ранее. Убедитесь, что входная транзитная проверка проверена. Используйте регулярное выражение lambda error, чтобы определить, какой код состояния следует использовать, когда вы возвращаете сообщение об ошибке из вашей лямбда-функции. Например:

    // Return An Error Message String In Your Lambda Function
    
    return context.fail('Bad Request: You submitted invalid input');
    
    // Here is what a Lambda Error Regex should look like.
    // Be sure to include the period and the asterisk so any text
    // after your regex is mapped to that specific HTTP Status Code
    
    Bad Request: .*
    
  • Ваш маршрут шлюза API должен вернуть это:

    HTTP Status Code: 400
    JSON Error Response: 
        {
            errorMessage: "Bad Request: You submitted invalid input"
        }
    
  • Я не вижу возможности скопировать эти настройки и повторно использовать их для разных методов, поэтому у нас есть много раздражающего избыточного ввода вручную!

Мои ответы на интеграцию выглядят следующим образом:

aws api gateway lambda error response handling

Ответ 3

Чтобы вернуть пользовательский объект ошибки в виде JSON, вам нужно перепрыгнуть через пару обручей.

Во-первых, вы должны пропустить Лямбду и передать ей стробированный объект JSON:

exports.handler = function(event, context) {
    var response = {
        status: 400,
        errors: [
            {
              code:   "123",
              source: "/data/attributes/first-name",
              message:  "Value is too short",
              detail: "First name must contain at least three characters."
            },
            {
              code:   "225",
              source: "/data/attributes/password",
              message: "Passwords must contain a letter, number, and punctuation character.",
              detail: "The password provided is missing a punctuation character."
            },
            {
              code:   "226",
              source: "/data/attributes/password",
              message: "Password and password confirmation do not match."
            }
        ]
    }

    context.fail(JSON.stringify(response));
};

Затем вы настраиваете отображение регулярных выражений для каждого из кодов состояния, которые вы хотите вернуть. Используя указанный выше объект, вы должны установить это регулярное выражение для 400:

.

* "статус": 400 *.

Наконец, вы настраиваете шаблон сопоставления для извлечения ответа JSON из свойства errorMessage, возвращаемого Lambda. Шаблон сопоставления выглядит следующим образом:

$input.path( '$. ErrorMessage')

Я написал статью об этом, которая более подробно освещена и объясняет поток ответов от Lambda до API Gateway: http://kennbrodhagen.net/2016/03/09/how-to-return-a-custom-error-object-and-status-code-from-api-gateway-with-lambda/

Ответ 4

1) Настройте свой ресурс шлюза API для использования Lambda Proxy Integration, установив флажок Используйте интеграцию Lambda Proxy " на экране" Запрос интеграции "в определении ресурса API-шлюза. (Или определить его в вашей конфигурации cloudformation/terraform/serverless/etc)

2) Измените свой лямбда-код двумя способами.

  • Обработать входящий event (1-й аргумент функции) соответствующим образом. Это уже не просто голая полезная нагрузка, она представляет весь HTTP-запрос, включая заголовки, строку запроса и тело. Пример ниже. Ключевым моментом является то, что телами JSON будут строки, требующие явного вызова JSON.parse(event.body) (не забудьте try/catch вокруг этого). Пример ниже.
  • Отвечайте путем вызова обратного вызова с нулевым значением, а затем объекта ответа, который предоставляет данные HTTP, включая statusCode, body и headers.
    • body должна быть строкой, поэтому JSON.stringify(payload) при необходимости
    • statusCode может быть числом
    • headers является объектом имен заголовков для значений

Пример аргумента события Lambda для интеграции прокси-сервера

{
    "resource": "/example-path",
    "path": "/example-path",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "US",
        "Content-Type": "application/json",
        "Host": "exampleapiid.execute-api.us-west-2.amazonaws.com",
        "User-Agent": "insomnia/4.0.12",
        "Via": "1.1 9438b4fa578cbce283b48cf092373802.cloudfront.net (CloudFront)",
        "X-Amz-Cf-Id": "oCflC0BzaPQpTF9qVddpN_-v0X57Dnu6oXTbzObgV-uU-PKP5egkFQ==",
        "X-Forwarded-For": "73.217.16.234, 216.137.42.129",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "queryStringParameters": {
        "bar": "BarValue",
        "foo": "FooValue"
    },
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
        "accountId": "666",
        "resourceId": "xyz",
        "stage": "dev",
        "requestId": "5944789f-ce00-11e6-b2a2-dfdbdba4a4ee",
        "identity": {
            "cognitoIdentityPoolId": null,
            "accountId": null,
            "cognitoIdentityId": null,
            "caller": null,
            "apiKey": null,
            "sourceIp": "73.217.16.234",
            "accessKey": null,
            "cognitoAuthenticationType": null,
            "cognitoAuthenticationProvider": null,
            "userArn": null,
            "userAgent": "insomnia/4.0.12",
            "user": null
        },
        "resourcePath": "/example-path",
        "httpMethod": "POST",
        "apiId": "exampleapiid"
    },
    "body": "{\n  \"foo\": \"FOO\",\n  \"bar\": \"BAR\",\n  \"baz\": \"BAZ\"\n}\n",
    "isBase64Encoded": false
}

Образец формы ответа обратного вызова

callback(null, {
  statusCode: 409,
  body: JSON.stringify(bodyObject),
  headers: {
    'Content-Type': 'application/json'
  }
})

Примечания - Я считаю, что методы на context, такие как context.succeed(), устарели. Они больше не документированы, хотя они все еще работают. Я думаю, что кодирование API обратного вызова - это правильная вещь в будущем.

Ответ 5

Для тех, кто пробовал все, задал этот вопрос и не смог выполнить эту работу (например, я), проверьте комментарий thedevkit на этот пост (сохранен мой день):

https://forums.aws.amazon.com/thread.jspa?threadID=192918

Воспроизводя его полностью ниже:

У меня были проблемы с этим самим, и я считаю, что новая линия персонажи являются виновниками.

foo. * будет соответствовать вхождениям "foo", за которыми следуют любые символы ИСКЛЮЧИТЬ новую строку. Обычно это решается путем добавления флага "/s", т.е. "foo. */s", но регулярное выражение Lambda error не похоже на это.

В качестве альтернативы вы можете использовать что-то вроде: foo (. |\n) *

Ответ 6

Я хотел, чтобы ошибка от Lambda была правильной ошибкой 500, после проведения большого количества исследований, придумал ниже, который работает:

В LAMBDA

Для хорошего ответа я возвращаюсь, как показано ниже:

exports.handler = (event, context, callback) => {
    // ..

    var someData1 =  {
        data: {
            httpStatusCode: 200,
            details: [
                {
                    prodId: "123",
                    prodName: "Product 1"
                },
                {
                    "more": "213",
                    "moreDetails": "Product 2"
                }
            ]
        }
    };
    return callback(null, someData1);
}

Для плохого ответа, возвращающегося как ниже

exports.handler = (event, context, callback) => {
    // ..

    var someError1 = {
        error: {
            httpStatusCode: 500,
            details: [
                {
                    code: "ProductNotFound",
                    message: "Product not found in Cart",
                    description: "Product should be present after checkout, but not found in Cart",
                    source: "/data/attributes/product"
                },
                {
                    code: "PasswordConfirmPasswordDoesntMatch",
                    message: "Password and password confirmation do not match.",
                    description: "Password and password confirmation must match for registration to succeed.",
                    source: "/data/attributes/password",
                }
            ]
        }
    };

    return callback(new Error(JSON.stringify(someError1)));
}

В интерфейсе API

Для GET METHOD, скажем GET/res1/service1:

Through Method Response > Add Response, added 3 responses:
- 200
- 300
- 400

Тогда

Through 'Integration Response' > 'Add integration response', create a Regex for 400 errors (client error):

Lambda Error Regex    .*"httpStatusCode":.*4.*

'Body Mapping Templates' > Add mapping template as:  
    Content-Type                 application/json  
    Template text box*           $input.path('$.errorMessage')  


Similarly, create a Regex for 500 errors (server error):

Lambda Error Regex    .*"httpStatusCode":.*5.*

'Body Mapping Templates' > Add mapping template as:  
    Content-Type                 application/json  
    Template text box*           $input.path('$.errorMessage')  

Теперь опубликуйте /res 1/service1, удалите опубликованный URL-адрес, который связан с приведенным выше лямбдой

Используемый расширенный клиентский клиент REST (или Postman), вы увидите надлежащие http-коды, такие как ошибка сервера (500) или 400, вместо 200 HTTP-кода ответа для всех запросов, которые были указаны в "httpStatusCode".

В "Dashboard" API, в API Gateway, мы можем видеть коды статуса http, как показано ниже:

400 и 500 ошибок

Ответ 7

Самый простой способ сделать это - использовать интеграцию LAMBDA_PROXY. Используя этот метод, вам не нужны специальные преобразования, которые необходимо установить в конвейер API Gateway.

Ваш объект возврата должен быть похож на фрагмент ниже:

module.exports.lambdaHandler = (event, context, done) => {
    // ...
    let response = {
        statusCode: 200, // or any other HTTP code
        headers: {       // optional
             "any-http-header" : "my custom header value"
        },
        body: JSON.stringify(payload) // data returned by the API Gateway endpoint
    };
    done(null, response); // always return as a success
};

У него есть несколько недостатков: нужно быть особенно осторожным в обработке ошибок и связывать вашу лямбда-функцию с конечной точкой шлюза API; что, если вы на самом деле не собираетесь использовать его где-либо еще, это не так уж важно.

Ответ 8

Я использую serverless 0.5. Вот как это работает, для моего случая

S-function.json:

{
  "name": "temp-err-test",
  "description": "Deployed",
  "runtime": "nodejs4.3",
  "handler": "path/to/handler.handler",
  "timeout": 6,
  "memorySize": 1024,
  "endpoints": [
    {
      "path": "test-error-handling",
      "method": "GET",
      "type": "AWS_PROXY",
      "responses": {
        "default": {
          "statusCode": "200"
        }
      }
    }
  ]
}

handler.js:

'use strict';
function serveRequest(event, context, cb) {
  let response = {
    statusCode: '400',
    body: JSON.stringify({ event, context }),
    headers: {
      'Content-Type': 'application/json',
    }
  };
  cb(null, response);
}
module.exports.handler = serveRequest;

Ответ 9

Так рекомендуется в AWS Compute Blog при использовании API Gateway. Проверка, чтобы убедиться, что интеграция работает с прямым вызовом Lambda.

var myErrorObj = {
    errorType : "InternalServerError",
    httpStatus : 500,
    requestId : context.awsRequestId,
    message : "An unknown error has occurred. Please try again."
}
callback(JSON.stringify(myErrorObj));

Для прямых Lambda-вызовов это, по-видимому, является лучшим решением для обработки на стороне клиента.