3

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

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

3 Comments

Yes! This worked with some minor tweaks. Answering my own question to explain.
See my answer below. I had to add the dependencies in maven, change the type of input, then reconfigure my API Gateway to use lambda proxy integration.
Thank you for pointing to aws-serverless-java-container, that's what I was looking for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.