Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@QueryValue does not work with API GW Rest API #1443

Open
JouperCoding opened this issue Aug 29, 2022 · 2 comments
Open

@QueryValue does not work with API GW Rest API #1443

JouperCoding opened this issue Aug 29, 2022 · 2 comments
Assignees
Labels
closed: cannot reproduce The issue cannot be reproduced

Comments

@JouperCoding
Copy link

JouperCoding commented Aug 29, 2022

Expected Behavior

When sending a request to a controller endpoint with @QueryValue for example ?foo=bar the expected outcome is that the value is provided to the variable.

@QueryValue String foo

Actual Behaviour

When deploying this to an AWS Lambda function integrated with a REST API GW using the following format version.
https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

The query string parameters does not seem to be parsed and provided properly to the @QueryValue.

  "queryStringParameters": {
    "parameter1": "value1",
    "parameter2": "value"
  },

The response will always be

"Required argument [String foo] not specified"

Steps To Reproduce

1: Create new Micronaut 3.6.1 project with

    implementation("io.micronaut.aws:micronaut-function-aws-api-proxy:$micronautFunctionAwsApiProxy")

2: Create a controller with a Get endpoint that requires a @QueryValue
3: Build and deploy to AWS Lambda with an API GW Proxy integration

Environment Information

Micronaut 3.6.1
GraalVM 22.2.0
AWS API GW - REST API

Example Application

No response

Version

3.6.1

@sdelamo
Copy link
Contributor

sdelamo commented Aug 30, 2022

It only works if you use Payload 1.0 format

I created an app with aws-lambda, aws-cdk amazon-api-gateway features.

https://micronaut.io/launch?type=DEFAULT&name=demo&package=com.example&javaVersion=JDK_11&lang=JAVA&build=GRADLE&test=JUNIT&features=amazon-api-gateway&features=aws-cdk&features=aws-lambda&version=3.6.1

I have a repository which shows it works with Amazon API gateway and Http Api. See how test-app.sh passes for both.

https://github.com/grails-core-issues-forks/micronaut-aws-issue-1443

import software.amazon.awscdk.services.apigatewayv2.alpha.HttpApi;
import software.amazon.awscdk.services.apigatewayv2.integrations.alpha.HttpLambdaIntegration;
import static software.amazon.awscdk.services.apigatewayv2.alpha.PayloadFormatVersion.VERSION_1_0;
.....


HttpLambdaIntegration integration = 
    HttpLambdaIntegration.Builder.create("HttpLambdaIntegration", function)
            .payloadFormatVersion(VERSION_1_0)
                .build();
HttpApi api = HttpApi.Builder.create(this, "micronaut-function-api")
    .defaultIntegration(integration)
    .build();

To run the script you will need:

Install AWS CDK CLI

Install npm. You can install in MacOS with homebrew.

Install AWS CDK CLI

npm install -g aws-cdk  

@JouperCoding
Copy link
Author

JouperCoding commented Sep 2, 2022

Hello @sdelamo

I have confirmed we are using payload version 1.0 with AWS API Gateway REST API. API GW Rest API only support that payload version currently, so that should not be the issue.

Perhaps I get this issue because our lambda is deployed as an native-image which uses a custom runtime handler we have created that replaces the MicronautLambdaRuntime handler?

When building and deploying to cloud we use
implementation("io.micronaut.aws:micronaut-function-aws-custom-runtime:$micronautFunctionAwsCustomRuntime")
and
extends AbstractMicronautLambdaRuntime<AwsProxyRequest, AwsProxyResponse, AwsProxyRequest, AwsProxyResponse>

Our handler looks like this.

/**
 * Replaces MicronautLambdaRuntime
 */
public class YggdrasilLambdaRuntime extends AbstractMicronautLambdaRuntime<AwsProxyRequest, AwsProxyResponse, AwsProxyRequest, AwsProxyResponse> {

	private static final Logger logger = LoggerFactory.getLogger(YggdrasilLambdaRuntime.class);

	private final long bootedAt;
	private long runningAt;
	private boolean reported;

	private MicronautLambdaHandler micronautLambdaHandler;

	public YggdrasilLambdaRuntime(long bootedAt){
		this.bootedAt = bootedAt;
		this.runningAt = 0;
		this.reported = false;
	}

	public static void main(String[] args) {
		long bootedAt = System.currentTimeMillis();
		try {
			YggdrasilLambdaRuntime yggdrasilLambdaRuntime = new YggdrasilLambdaRuntime(bootedAt);
			yggdrasilLambdaRuntime.run(args);
		} catch (Exception ex){
			logger.error("Lambda runtime could not start", ex);
		}
	}

	@Override
	protected RequestHandler<AwsProxyRequest, AwsProxyResponse> createRequestHandler(String... args) {
		try {
			if(micronautLambdaHandler == null) {
				micronautLambdaHandler = new MicronautLambdaHandler(createApplicationContextBuilderWithArgs(args));

				if(!reported) {
					this.runningAt = System.currentTimeMillis();

					Optional.of(micronautLambdaHandler.getApplicationContext()).ifPresent(applicationContext -> {
						monitorLambdaColdStart(applicationContext, bootedAt, runningAt);
					});

					this.reported = true;
				}
			}
			return micronautLambdaHandler;
		} catch (ContainerInitializationException e) {
			throw new ConfigurationException("Exception thrown instantiating MicronautLambdaRuntimeHandler", e);
		}
	}

	private void monitorLambdaColdStart(ApplicationContext applicationContext, long bootedAt, long runningAt){
		long coldStart = (runningAt - bootedAt);
		if(applicationContext.containsBean(MetricsService.class)) {
			try {
				MetricsService metricsService = applicationContext.getBean(MetricsService.class);
				metricsService.lambdaColdStart(coldStart);
			} catch (NonUniqueBeanException ex) {
				logger.info("Unable to send cold start metric, no metrics service found");
			}
		}
	}

}

@sdelamo sdelamo reopened this Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed: cannot reproduce The issue cannot be reproduced
Projects
None yet
Development

No branches or pull requests

2 participants