क्या अमेज़ॅन एपीआई गेटवे द्वारा लौटे http स्थिति कोड को बदलने का एक तरीका है?


95

उदाहरण के लिए, यदि मैं अमान्य पैरामीटरों के लिए एक विशिष्ट 400 त्रुटि या शायद 201 को लौटना चाहता हूं जब लैम्बडा फ़ंक्शन कॉल का परिणाम होता है।

मुझे अलग-अलग http स्टेटस कोड्स चाहिए, लेकिन ऐसा लगता है कि एपीआई गेटवे हमेशा एक 200 स्टेटस कोड लौटाता है, भले ही लैम्बडा फ़ंक्शन एक त्रुटि लौटा रहा हो।


2
इसलिए ऐसा लगता है कि मुझे जो समस्या हो रही थी, वह यह था कि मैं एक कस्टम त्रुटि प्रकार लौटा रहा था - जो त्रुटि बनाता है। regex ठीक से काम नहीं करता है। लैम्ब्डा से विफल प्रतिक्रिया में एक मानक स्ट्रिंग वापस करने से नीचे का समाधान कार्य हो जाएगा - हालांकि, अपनी स्वयं की कस्टम त्रुटि ऑब्जेक्ट को वापस करना, नहीं होगा।
मंकीबोनी

मेरा समाधान था कि मैं सेरेलवेज़ संस्करण 0.5 से 1.0 में बदलूं। इसके अलावा, मैं Serveless प्रलेखन से प्रतिक्रिया का उपयोग कर रहा हूं, एक संपत्ति के रूप में प्रतिक्रिया ऑब्जेक्ट में स्थिति कोड निर्दिष्ट कर रहा हूं। आशा है कि यह मदद करता है
रेलू मेसरोस

जवाबों:


79

अपडेट 20-9-2016 तक

अमेज़न ने आखिरकार लैम्बडा प्रॉक्सी इंटीग्रेशन का उपयोग करके इसे आसान बना दिया । यह आपके लैम्ब्डा फ़ंक्शन को उचित HTTP कोड और हेडर वापस करने की अनुमति देता है:

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

context.succeed(response);

एपीआई गेटवे में अलविदा अनुरोध / प्रतिक्रिया मानचित्रण कहें!

विकल्प 2

Aws-serverless-express का उपयोग करके लैम्ब्डा / एपीआई गेटवे के साथ एक मौजूदा एक्सप्रेस ऐप को एकीकृत करें ।


मैं इसे एकीकृत नहीं कर सकता, मेरा मतलब है, मुझे 200 का दर्जा मिला है और बनाई गई प्रतिक्रिया (बनाई गई त्रुटि)। क्या मैं कुछ भूल रहा हूँ ? "S-function.json" कैसा दिखता है?
रेलू मेसरोस

सबसे सरल उदाहरण के लिए, AWS के अपने लैम्ब्डा ब्लूप्रिंट को देखें, जिसे microservice-http-endpoint (AWS लैम्ब्डा कंसोल में) कहा जाता है। आप "s-function.json" का उल्लेख करते हैं, जो लगता है कि आप सर्वर रहित फ्रेमवर्क ( serverless.com ) का उपयोग कर रहे हैं । यह पूरी तरह से एक और जानवर है और अर्स-सर्वर रहित-एक्सप्रेस या 'रॉ' लैम्बडा / एपीआई गेटवे के साथ भ्रमित नहीं होना चाहिए। मेरा उत्तर यह वर्णन नहीं करता है कि सर्वरलेस फ्रेमवर्क का उपयोग करके यह काम कैसे किया जाए।
एरिक इजेकेलेनबोम

7
किसी को भी आश्चर्य हो, यह नई callbackशैली का उपयोग करके भी प्राप्त किया जा सकता है । बस करो callback(null, {statusCode: 200, body: 'whatever'})
विदरशिन

1
@ सुशील हाँ, आप ऊपर दिए गए प्रतिक्रिया चर की तरह ही JSON लौटाएँ।
चाचा

8
@ सुशील मैंने इसे लेथड्रोक्साइट इंट्रोगेशन और रिटर्निंग के साथ अजगर में हल किया हैreturn { "isBase64Encoded": True, "statusCode": 200, "headers": { }, "body": "" }
आर जैकब

74

यहां कस्टम HTTP स्थिति कोड और एक कस्टम वापस करने का सबसे तेज़ तरीका है errorMessage:

API गेटवे डैशबोर्ड में, निम्न कार्य करें:

  1. में विधि आपके लिए संसाधन , पर क्लिक करें विधि प्रतिक्रिया
  2. में HTTP स्थिति मेज, क्लिक करें ऐड प्रतिक्रिया और प्रत्येक HTTP स्थिति कोड आप उपयोग करना चाहते हैं में जोड़ें।
  3. में विधि आपके लिए संसाधन , पर क्लिक करें एकीकरण प्रतिक्रिया
  4. आपके द्वारा पहले बनाए गए प्रत्येक HTTP स्थिति कोड के लिए एक एकीकरण प्रतिक्रिया जोड़ें । सुनिश्चित करें कि इनपुट passthrough की जाँच की गई है। जब आप अपने लैम्ब्डा फ़ंक्शन से कोई त्रुटि संदेश लौटाते हैं तो पहचानने के लिए कि किस स्थिति कोड का उपयोग किया जाना चाहिए, यह पहचानने के लिए लैम्ब्डा त्रुटि रेगेक्स का उपयोग करें । उदाहरण के लिए:

    // 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: .*
    
  5. आपका एपीआई गेटवे मार्ग इसे वापस करना चाहिए:

    HTTP Status Code: 400
    JSON Error Response: 
        {
            errorMessage: "Bad Request: You submitted invalid input"
        }
    
  6. मुझे इन सेटिंग्स को कॉपी करने और विभिन्न तरीकों के लिए फिर से उपयोग करने का कोई तरीका नहीं दिखता है, इसलिए हमें बहुत कष्टप्रद मैनुअल इनपुट करना पड़ता है!

मेरी एकीकरण प्रतिक्रियाएं इस तरह दिखती हैं:

aws एपीआई गेटवे लंबो त्रुटि प्रतिक्रिया हैंडलिंग


3
इसलिए ऐसा लगता है कि मेरा मुद्दा यह था कि रेगेक्स ट्रिगर कभी भी काम नहीं कर रहा था क्योंकि मैं लैम्बडा से एक त्रुटि वस्तु को असफल विधि में लौटाता था, बजाय केवल एक स्ट्रिंग के। जैसेreturn context.fail(new Error('bad one'))
मंकीबोन जूल

7
@kalisjoshua I ने हाल ही में एपीआई गेटवे / लैंबडा
कार्ल

9
पायथन लाम्बा के लिए संदर्भ के बराबर क्या है?
रूटबर्न

1
अजगर के लिए: एक अपवाद बढ़ाएं। देखें docs.aws.amazon.com/lambda/latest/dg/python-exceptions.html
devxoul

1
क्या गैर-त्रुटि प्रतिक्रियाओं में स्थिति कोड को बदलने का कोई तरीका नहीं है? क्या होगा अगर मैं बनाई गई वस्तु के साथ "201 क्रिएटेड" भेजना चाहता हूं?
बेन डेविस

18

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 प्रतिक्रिया निकालने के लिए एक मैपिंग टेम्पलेट सेट करते हैं। मैपिंग टेम्प्लेट इस तरह दिखता है:

$ Input.path ( '$। ErrorMessage')

मैंने इस पर एक लेख लिखा है जो अधिक विस्तार में जाता है और लैम्ब्डा से एपीआई गेटवे तक प्रतिक्रिया प्रवाह को यहां बताता है: http://kennbrodhagen.net/2016/03/09/how-to-return-a-custom-error-object -और-स्थिति-कोड-से-api-प्रवेश द्वार-साथ-लैम्ब्डा /


@kennbrodhagen क्या आप एपीआई गेटवे और जावा लैम्बडास के बारे में जानते हैं? मैं एक ही रेग एक्सप का एक प्रकार का उपयोग कर रहा हूं, और यह मेरे लिए काम नहीं कर रहा है। मैं उपयोग करता हूं। * स्टेटसकोड ": 422. *
पेरिमोश जूल

@Perimosh इस लेख की जाँच करें जो बताता है कि जावा अपवाद के साथ यह कैसे करना है: aws.amazon.com/blogs/compute/…
kennbrodhagen

10

1) एपीआई गेटवे संसाधन परिभाषा के "एकीकरण अनुरोध" स्क्रीन पर "लैम्बडा प्रॉक्सी एकीकरण का उपयोग करें" लेबल वाले चेकबॉक्स की जांच करके लैम्ब्डा प्रॉक्सी इंटीग्रेशन का उपयोग करने के लिए अपने एपीआई गेटवे संसाधन को कॉन्फ़िगर करें । (या इसे अपने क्लाउडफॉर्म / टेराफॉर्म / सर्वर रहित / आदि कॉन्फिगर में परिभाषित करें)

2) अपने लैम्ब्डा कोड को 2 तरीकों से बदलें

  • आने वाले event(पहले फ़ंक्शन तर्क) को उचित रूप से संसाधित करें । यह अब केवल नंगे पेलोड नहीं है, यह हेडर, क्वेरी स्ट्रिंग और बॉडी सहित पूरे HTTP अनुरोध का प्रतिनिधित्व करता है। नीचे का नमूना। मुख्य बिंदु यह है कि JSON निकायों में स्पष्ट JSON.parse(event.body)कॉल की आवश्यकता के तार होंगे (मत भूलनाtry/catch )। उदाहरण नीचे है।
  • तो अशक्त एक प्रतिक्रिया उद्देश्य यह है कि सहित HTTP विवरण प्रदान करता है के साथ कॉलबैक फोन करके जवाब statusCode, body, और headers
    • bodyएक तार होना चाहिए, इसलिए JSON.stringify(payload)आवश्यकतानुसार करें
    • statusCode एक संख्या हो सकती है
    • headers मानों के लिए शीर्षलेख नामों का ऑब्जेक्ट है

प्रॉक्सी एकीकरण के लिए नमूना लैंबडा इवेंट तर्क

{
    "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()को पदावनत किया जाता है। वे अब प्रलेखित नहीं हैं, हालांकि वे अभी भी काम करने लगते हैं। मुझे लगता है कि कॉलबैक एपीआई के लिए कोडिंग करना सही बात है।


यह काम नहीं करता। मुझे इस संपूर्ण प्रतिक्रिया आउटपुट के साथ अभी भी 200 का दर्जा मिला है। वास्तव में 409 का दर्जा लौटाने के लिए आपी को सेट नहीं कर सकते
एंडी एन

7

मैं चाहता था कि लंबोदर से एक त्रुटि 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)));
}

एपीआई गेटवे पर

GET METHOD के लिए, GET of / 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')  

अब, प्रकाशित / res1 / service1, प्रकाशित URL को हिट करें, जो कि लैम्बडा से ऊपर जुड़ा हुआ है

उन्नत REST क्लाइंट (या पोस्टमैन) क्रोम प्लगइन का इस्तेमाल किया, आपको "httpStatusCode" में दिए गए सभी अनुरोधों के लिए 200 http प्रतिक्रिया कोड के बजाय सर्वर त्रुटि (500) या 400 जैसे उचित http कोड दिखाई देंगे।

एपीआई गेटवे में एपीआई के 'डैशबोर्ड' से, हम नीचे की तरह http स्थिति कोड देख सकते हैं:

400 और 500 त्रुटियां


7

ऐसा करने का सबसे आसान तरीका है LAMBDA_PROXY एकीकरण का उपयोग करना । इस पद्धति का उपयोग करके, आपको एपीआई गेटवे पाइपलाइन में स्थापित करने के लिए किसी विशेष परिवर्तन की आवश्यकता नहीं है।

आपकी वापसी वस्तु नीचे दिए गए स्निपेट के समान होगी:

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

इसमें कुछ कमियां हैं: त्रुटि से निपटने के लिए विशेष रूप से सावधान रहना, और एपीआई गेटवे समापन बिंदु पर अपने लंबो फ़ंक्शन को युग्मित करना; उस ने कहा, यदि आप वास्तव में इसे कहीं और उपयोग नहीं करने जा रहे थे, तो यह इतनी समस्या नहीं है।


6

उन लोगों के लिए जिन्होंने इस सवाल पर सब कुछ करने की कोशिश की और यह काम नहीं कर सके (मेरी तरह), इस पोस्ट पर thedevkit टिप्पणी की जाँच करें (मेरा दिन बचाया):

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

नीचे इसे पूरी तरह से प्रस्तुत कर रहा है:

मेरे पास इस मुद्दे के साथ खुद है, और मुझे विश्वास है कि न्यूलाइन वर्ण अपराधी हैं।

foo। * "फू" की घटनाओं का मिलान किसी भी वर्ण द्वारा किया जाएगा। आमतौर पर इसे 's / s' फ्लैग को जोड़कर हल किया जाता है, अर्थात "foo। * / S", लेकिन लैम्ब्डा एरर रेगेक्स इसका सम्मान नहीं करता है।

एक विकल्प के रूप में आप कुछ का उपयोग कर सकते हैं जैसे: फू (? | \ N) *


अद्भुत खोज! यह सिर्फ मेरे सिर पीटने के घंटे मुझे बचा लिया! और इसके दूर से स्पष्ट है।
मिरको वुकुसीव

Mirko, मुझे खुशी है कि यह आपकी मदद की!
कार्लोस बैलॉक

2

एपीआई गेटवे का उपयोग करते समय एडब्ल्यूएस कंप्यूट ब्लॉग पर इसकी सिफारिश कैसे की जाती है। यह देखने के लिए कि एकीकरण प्रत्यक्ष लैम्ब्डा आह्वान के साथ काम करता है या नहीं।

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

प्रत्यक्ष लैम्ब्डा इनवोकेशन के लिए, यह क्लाइंट-साइड पर सबसे अच्छा समाधान पार्सिंग प्रतीत होता है।


क्या होगा अगर उदाहरण एक मेमने से लेकर लंबोदर कॉल का था। क्या यह अभी भी है जिसे लाम्बा लौटेगा? और मैं कैसे कॉलिंग लैम्ब्डा पर httpStatus पढ़ सकता हूं।
रॉड

1

मैं सर्वर रहित 0.5 का उपयोग कर रहा हूं। यह मेरे काम के लिए कैसे काम करता है

एस-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;

1

यदि आप प्रॉक्सी का उपयोग नहीं करना चाहते हैं, तो आप इस टेम्पलेट का उपयोग कर सकते हैं:

#set($context.responseOverride.status =  $input.path('$.statusCode'))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.