Access/get query parameters in aws lambda function

Hello everyone,

I am using eclipse. I am creating rest api using aws lambda java with serverless framework. I am having issue to understand how to define query parameters in serverless yml file and access them in the code, i am not able access them.

This is how i have defined my lambda function with query parameters in serverless.yml file.

functions:
GetHistoryList:
handler: com.services.handler.GetTHistoryListHandler
events:
- http:
path: api/history/list
method: GET
integration: lambda
private: true
cors: true
request:
template:
application/json: >
{
“memberId” : “$input.params(‘memberId’)”,
“fromDate” : “$input.params(‘fromDate’)”,
“toDate” : “$input.params(’‘toDate’’)”
}

I am trying access in my code like this:
public class GetTHistoryListHandler extends RequestHandler<Map<String, Object>, Response> {

@Override
protected Response handleRequest(Map<String, Object> input, Context context)  {
    String memberId= ((Map<String, String>) input.get("memberId")).get("memberId");
    String fromDate= ((Map<String, String>) input.get("fromDate")).get("fromDate");
    String toDate= ((Map<String, String>) input.get("toDate")).get("toDate");

}

My api url is like this:

GET - https://host.com/dev/api/history/list?memberId=57692&fromDate=2017-06-16&toDate=2017-06-17

I deployed into aws lambda. I am not able access query params.

Please confirm me, what i have defined in yml and access them are correct or not.

Thanks,
Bhasky

@bhaskyknl Indentation is important for YAML files. Can you please add ```yaml on the line before your serverless.yml and ``` on the line blow so that it maintains the correct formatting?


functions:
GetHistoryList:
handler: com.services.handler.GetTHistoryListHandler
events:
- http:
path: api/history/list
method: GET
integration: lambda
private: true
cors: true
request:
template:
application/json: > 
{
"memberId" : "$input.params('memberId')",
"fromDate" : "$input.params('fromDate')",
"toDate" : "$input.params(''toDate'')"
}

Thanks for replying…

you are saying like this?

functions:
GetHistoryList:
handler: com.services.handler.GetTHistoryListHandler
events:
- http:
path: api/history/list
method: GET
integration: lambda
private: true
cors: true
request:
template:
application/json: > 
{
"memberId" : "$input.params('memberId')",
"fromDate" : "$input.params('fromDate')",
"toDate" : "$input.params(''toDate'')"
}

@bhaskyknl

If you do it correctly then your message will look like:

functions:
  GetHistoryList:
    handler: com.services.handler.GetTHistoryListHandler
    events:
      - http:
    path: api/history/list

Instead of

functions: GetHistoryList: handler: com.services.handler.GetTHistoryListHandler events: - http: path: api/history/list

If you’re using code tags them remove them.

I have correct indentation in my serverless.yml file, however i pasted here in forum, it is not formatting.

Is there any update on my issue?

Hi @bhaskyknl,
I think your mistake is that your template is incorrect since you have double single quotes around toDate (it must be "toDate" : "$input.params('toDate')" instead of "toDate" : "$input.params(''toDate'')".

A few side notes:

  1. protected Response handleRequest cannot be right. The visibility must be public!
  2. Are you using the integration type integration: lambda on purpose? IMO lambda-proxy is much easier to use and gives you more flexibility. See Docs and Java Template
  3. Since you are using Java, you might be interested in my Java framework JRestless allowing you to use JAX-RS on AWS-Lambda (for lambda-proxy, only).

Full Example

serverless.yml

service: history

provider:
  name: aws
  runtime: java8
  stage: dev
  region: eu-central-1

package:
  artifact: build/distributions/deployable.zip

functions:
  GetHistoryList:
    handler: com.services.handler.GetTHistoryListHandler
    events:
      - http:
          path: api/history/list
          method: GET
          integration: lambda
          request:
            template:
              application/json: >
                {
                  "memberId" : "$input.params('memberId')",
                  "fromDate" : "$input.params('fromDate')",
                  "toDate" : "$input.params('toDate')"
                }

package com.services.handler;

import java.util.Map;

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

public class GetTHistoryListHandler implements RequestHandler<Map<String, Object>, GetTHistoryListHandler.Response>{

	@Override
	public GetTHistoryListHandler.Response handleRequest(Map<String, Object> input, Context context) {
		return new Response((String) input.get("memberId"), (String) input.get("fromDate"),
				(String) input.get("toDate"));
	}

    public static class Response {
    	private final String memberId;
    	private final String fromDate;
    	private final String toDate;
		Response(String memberId, String fromDate, String toDate) {
			super();
			this.memberId = memberId;
			this.fromDate = fromDate;
			this.toDate = toDate;
		}
		public String getMemberId() {
			return memberId;
		}
		public String getFromDate() {
			return fromDate;
		}
		public String getToDate() {
			return toDate;
		}
    }
}

build.gradle (just for completeness)

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.amazonaws:aws-lambda-java-core:1.1.0'
}

task buildZip(type: Zip) {
	archiveName = "deployable.zip"
	from compileJava
	from processResources
	into('lib') {
		from configurations.runtime
	}
}
build.dependsOn buildZip

Thanks for the update. I am able to access query params now.

I went through the doc using lambda-proxy. Can you please provide if you have any example for HTTP POST method using java for lambda-proxy?

I am using spring boot. After i deployed into aws lambda, i am getting aws gateway timeout error for 1st run, subsequent runs gives result within 30 mins. Is there a solution for this timeout issue?

Thanks,
Bhasky

regarding binary
check this: How to add binary media type to serverless.yml
The important steps are to

  • to register binary media types (that’s not possible with serverless - you either need to do this manually or use some plugin)
  • to send a “Content-Type” request-header with one of the registered binary media types as value
  • decode the base64 encoded body, manually

regarding the timeout:

  • Spring Boot is a probably a little heavy… try to unregister everything that’s not really required (add some logging to see where you actually waste the time)
  • increase the timeout of your lambda function to 60s

Thanks for the update.

Can you please provide an example how we mention lambda-proxy / aws-proxy / aws_proxy in serverless.yml and how we access the request/path variable using aws lambda java for PUT method?

Thanks,
Bhasky

Hi @bhaskyknl ,

  1. You either remove integration: lambda, or replace it by integration: lambda-proxy.
  2. You can get the resolved path from the “input map”: (String) input.get("path")
  3. You can get the unresolved path from the “input map”: (String) input.get("resource")
  4. You can get the path params from the “input map”: (Map<String, String>) input.get("pathParams")
  5. You can get the query params from the “input map”: (Map<String, String>) input.get("queryStringParameters")

See: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-input-format