===== API Gateway ===== Real-time applications with API Gateway WebSockets and AWS Lambda https://serverless.com/blog/api-gateway-websockets-support/ Calling API gateways via generated SDKs https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-generate-sdk-javascript.html ===== REST API vs HTTP API ===== https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html REST-Api has more functionality regarding inspection. ===== Lambda behind the API gateway ===== https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax ==== Fallpit: Invoke Lambda POST ==== The API must invoke the backend Lambda function using the **HTTP method POST**. https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax Otherwise you will get * a 500 error on the Gateway * a 403 error on the Lambda, behind the Gateway https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-lambda-template-invoke-error/ ==== Debugging ==== If a Lambda does not behave as intended - use the **Test button**. ONe can see much more exceptions in there. {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/gDyYDmOwNf.png}} {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/0SwqtTPgvP.png}} ==== Java Lambda behind the API gateway ==== https://www.baeldung.com/aws-lambda-api-gateway Example: https://github.com/skipidar/aws-javalambda-behind-apigateway === Java signature === There are obligations on the Java-Lambda signature, when executed behind Gateway. It is important to have * InputStream inputStream, * OutputStream outputStream in the interface of the Lambda - otherwise the API Gateway will throw exceptions Dependencies dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.1' implementation 'com.google.code.gson:gson:2.8.6' testImplementation 'org.apache.logging.log4j:log4j-api:2.13.0' testImplementation 'org.apache.logging.log4j:log4j-core:2.13.0' testImplementation 'org.apache.logging.log4j:log4j-slf4j18-impl:2.13.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.0' compile 'com.googlecode.json-simple:json-simple:1.1.1' } package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.nimbusds.oauth2.sdk.TokenRequest; import no.nav.security.mock.oauth2.MockOAuth2Server; import no.nav.security.mock.oauth2.token.OAuth2TokenCallback; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.*; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; // Handler value: example.Handler public class Handler implements RequestStreamHandler { /** * The handleRequest interface, as below, * with InputStream, OutputStream * * when Lambda is used with the API Gateway - is required. * * https://www.baeldung.com/aws-lambda-api-gateway * * @param inputStream * @param outputStream * @param context * @throws IOException */ public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { JSONParser parser = new JSONParser(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); JSONObject responseJson = new JSONObject(); JSONObject event = null; try { event = (JSONObject) parser.parse(reader); handleEvent(event, responseJson, inputStream, outputStream, context); } catch (ParseException e) { responseJson.put("statusCode", 400); responseJson.put("exception", e); } // example response JSONObject obj2 = new JSONObject(); obj2.put("Content-Type", "application/json"); responseJson.put("statusCode", 200); responseJson.put("headers", obj2); responseJson.put("body", "hello world"); // writing the result into the OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8"); writer.write(responseJson.toString()); writer.close(); } === Return format of Lambda === Lambdas needs to return JSON, to be capable to be used from the gateway. https://docs.amazonaws.cn/en_us/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format // Handler value: example.Handler public class Handler implements RequestStreamHandler { public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { // example response JSONObject obj2 = new JSONObject(); obj2.put("Content-Type", "application/json"); responseJson.put("statusCode", 200); responseJson.put("headers", obj2); responseJson.put("body", "hello world"); // writing the result into the OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8"); writer.write(responseJson.toString()); writer.close(); ==== Use Lambda Proxy integration ==== When a client submits an API request, API Gateway passes to the integrated Lambda function the raw request as-is: That means, that the option `Use Lambda Proxy integration` * **deactivates** the **"Mapping Templates"** * https://aws.amazon.com/premiumsupport/knowledge-center/custom-headers-api-gateway-lambda/ {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/vC2XDM5VDx.png}} This is the most powerful integration: - **\{{proxy}}** sends all resources - to the Lambda - **ANY** - accepts all methods https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-proxy-resource%3Ficmpid=docs_apigateway_console {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/M51LDfQis7.png}} * Still the API must be deployed to a "stage" * Minimum one resource must be present after the stage - or you will get "{"message":"Missing Authentication Token"}" After that the lambda reacts on curl -X POST https://s5oi8r61hk.execute-api.eu-west-1.amazonaws.com/stage/someresourcehere/1/2/bla/blub/enigma21/ curl -X GET https://s5oi8r61hk.execute-api.eu-west-1.amazonaws.com/stage/2/ ==== Mapping Templates ==== Can be used to add custom headers from the API gateway to the Lambda https://aws.amazon.com/premiumsupport/knowledge-center/custom-headers-api-gateway-lambda/ ==== Token Exchange ===== The token exchange is possible with 2 pieces: * obtain a new token at the lambda authorizer * set the header via VLT as in https://stackoverflow.com/questions/40585016/is-it-possible-to-add-an-http-header-from-aws-custom-auth-on-api-gateway ===== A Detailed Overview of AWS API Gateway ===== An overview of the API gateway functions. https://www.alexdebrie.com/posts/api-gateway-elements/ {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/44ovAxhCbW.png}} {{https://s3.eu-central-1.amazonaws.com/alf-digital-wiki-pics/sharex/QuF6kGfybF.png}}