Sullhouse
Sullhouse

Reputation: 73

Get Mapping Template from API Gateway as JSON in AWS Lambda Java Project

I've set up an API Gateway GET method integrated with a bare-bones AWS Lambda function. I've enabled the Request Body Passthrough on the Integration Request to the pre-set Method request passthrough template.

I would like to do different things based on the resource-path of the request. For example, if the path is /foo, I would interpret the foo request, or /bar would interpret as the bar request, with the same Lambda function. So I need to switch based on the resource-path within the Lambda function itself.

I'm getting stuck accessing the mapped payload template. All the data should be there according to the AWS help. But in java, I can't figure out how to convert the input from API gateway into parsable json using Jackson, org.json, or json-path.

Here is my Lambda code. Any help on how to get "resource-path", or any of the method request passthrough, from the API Gateway GET would be appreciated.

import org.json.JSONObject;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class LambdaFunctionHandler implements RequestHandler<Object, Object> {

@Override
public Object handleRequest(Object input, Context context) {
    JSONObject inputJson = new JSONObject(input.toString());
    JSONObject contextJson = inputJson.getJSONObject("context");

    String resourcePath = contextJson.getString("resource-path");

    return resourcePath;
}

}

And here is what I believe is being sent into the function as input:

{
  "body-json" : {},
  "params" : {
    "path" : {},
    "querystring" : {},
    "header" : {}
  },
  "stage-variables" : {},
  "context" : {
    "account-id" : "xxxxxxxxx",
    "api-id" : "xxxxxxxxx",
    "api-key" : "xxxxxxxxx",
    "authorizer-principal-id" : "",
    "caller" : "xxxxxxxxx",
    "cognito-authentication-provider" : "",
    "cognito-authentication-type" : "",
    "cognito-identity-id" : "",
    "cognito-identity-pool-id" : "",
    "http-method" : "GET",
    "stage" : "test-invoke-stage",
    "source-ip" : "test-invoke-source-ip",
    "user" : "xxxxxxxxxxxxxxxx",
    "user-agent" : "Apache-HttpClient/4.5.x (Java/1.8.0_112)",
    "user-arn" : "arn:aws:iam::230537478972:root",
    "request-id" : "test-invoke-request",
    "resource-id" : "75bakm",
    "resource-path" : "/text"
  }
}

But I'm getting:

{
"errorMessage": "Expected a ':' after a key at 11 [character 12 line 1]",
"errorType": "org.json.JSONException",
"stackTrace": [
"org.json.JSONTokener.syntaxError(JSONTokener.java:433)",
"org.json.JSONObject.<init>(JSONObject.java:216)",
"org.json.JSONObject.<init>(JSONObject.java:323)",
"xxx.LambdaFunctionHandler.handleRequest(LambdaFunctionHandler.java:12)"
  ]
}

Upvotes: 3

Views: 3677

Answers (2)

Sullhouse
Sullhouse

Reputation: 73

Thanks to Ka Hou leong for the direction, I've solved with the following:

1) Added dependency in Maven for aws-serverless-java-container

<dependency>
    <groupId>com.amazonaws.serverless</groupId>
    <artifactId>aws-serverless-java-container-core</artifactId>
    <version>0.4</version>
</dependency>

2) Modified my LambdaFunctionHandler class to use AwsProxyRequest and AwsProxyResponse:

import com.amazonaws.serverless.proxy.internal.model.AwsProxyRequest;
import com.amazonaws.serverless.proxy.internal.model.AwsProxyResponse;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class LambdaFunctionHandler implements RequestHandler<AwsProxyRequest, Object> {

    public Object handleRequest(AwsProxyRequest input, Context context) {
        AwsProxyResponse response = new AwsProxyResponse();
        String resourcePath = input.getRequestContext().getResourcePath();

        response.setStatusCode(200);
        response.setBody(resourcePath);
    return response;
    }
}

3) Modified my API Gateway method Integration Request settings to Use Lambda Proxy Integration.

From here I have access to everything in the input object as an AwsProxyRequest, and will manipulate response as an AwsProxyResponse with anything I want to respond with.

Upvotes: 4

Ka Hou Ieong
Ka Hou Ieong

Reputation: 6515

You can write your own POJO to match the request from API Gateway, then you will be able to access the resource path from a getter.

POJOs example:

public class LambdaFunctionHandler implements RequestHandler<Object, Object> {

    @Override
    public Object handleRequest(AwsProxyRequest input, Context context) {
        String resourcePath = input.getRequestContext().getResourcePath();

        return resourcePath;
    }

}

public class AwsProxyRequest {

    //-------------------------------------------------------------
    // Variables - Private
    //-------------------------------------------------------------
    private ApiGatewayRequestContext requestContext;
    ....

    //-------------------------------------------------------------
    // Methods - Getter/Setter
    //-------------------------------------------------------------

    public ApiGatewayRequestContext getRequestContext() {
        return requestContext;
    }


    public void setRequestContext(ApiGatewayRequestContext requestContext) {
        this.requestContext = requestContext;
    }

    ....

}

public class ApiGatewayRequestContext {

    //-------------------------------------------------------------
    // Variables - Private
    //-------------------------------------------------------------

    private String resourcePath;
    ...

    //-------------------------------------------------------------
    // Methods - Getter/Setter
    //-------------------------------------------------------------

    public String getResourcePath() {
        return resourcePath;
    }


    public void setResourcePath(String resourcePath) {
        this.resourcePath = resourcePath;
    }

    ....
}

If you want the full proxy request POJO, you can find them from here.

Upvotes: 1

Related Questions