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

Changed behaviour of routing evalution between Micronaut 3 and 4? #2078

Open
dniel opened this issue Mar 8, 2024 · 10 comments
Open

Changed behaviour of routing evalution between Micronaut 3 and 4? #2078

dniel opened this issue Mar 8, 2024 · 10 comments
Assignees

Comments

@dniel
Copy link

dniel commented Mar 8, 2024

Expected Behavior

In Micronaut 4 , when deploying application type lambda in the API Gateway, the API mapping in the gateway should be ignored, like it is in Micronaut 3.

Actual Behaviour

Its a REST API accessibly via AWS API Gateway under the api mapping /myapp and uses the Application type with io.micronaut.function.aws.proxy.payload1.ApiGatewayProxyRequestEventFunction routing in Micronaut to route to the correct @Controller in the lambda.

When testing this from postman to the api-gateway url, the request event looks like this
Notice that the API Gateway has added the API mapping to the path property, but not to the resource property.

{
  "path": "/myapp/users",
  "resource": "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}

This works in Micronaut 3 using io.micronaut.function.aws.proxy.MicronautLambdaHandler because it seems like Micronaut 3 uses the "resource": "/users" property to evaluate the routing to correct method in the Controller.

When using Micronaut 3, I can change the API mapping of my Lambda in API Gateway to whatever I need and deploy the same lambda in different api endpoint, and it will still call my Users controller and return the expected response, because it use the "resource" property to route to map to the Users Controller, Micronaut 3 ignores the path the lambda is hosted on in the API Gateway.

The raw json event payload received by the Lambda looks like this

{
  "path": "/whatever/users",
  "resource":  "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}

Upgrading to Micronaut 4, this will break and return 404 instead.

  • Micronaut 3 seems to use property "resource" in the lambda event for routing.
  • Micronaut 4 seems to use property "path" in the lamnda event for routing.
  • resource and path does not have the same values, routing breaks when upgrading.

In Micronaut 4 using the handler io.micronaut.function.aws.proxy.payload1.ApiGatewayProxyRequestEventFunction it seems like it has been changed which property in the request event that is evaluated for routing and its now the path-property instead, which by API Gateway includes the context-root set in the api mapping from Api Gateway, which means that the context root in the lambdas application.yml must now be set to the same.

A request as the one below will work in Micronaut 3, but not in Micronaut 4.

{
  "path": "/myapp/users",
  "resource": "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}

This means that the same lambda can't be used from different API Gatway APIs in Micronaut4 but could in Micronaut3.

Steps To Reproduce

  • Create a lambda with micronaut 3 using io.micronaut.function.aws.proxy.MicronautLambdaHandler with context-root: /
  • Create a controller responding to /users and return 200 ok.
  • Publish the lambda and go to the AWS Lambda console and "Test" invoke with something like
{
  "path": "/whatever",
  "resource":  "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}
  • the result should be 200 ok.
  • Upgrade the Lambda to Micronaut4 and handler io.micronaut.function.aws.proxy.payload1.ApiGatewayProxyRequestEventFunction
  • Publish new version and "Test" invoke again with the same event as above
{
  "path": "/whatever",
  "resource":  "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}
  • the response is 404

Environment Information

  • Micronaut 3.8.3 upgrade to Micronaut 4.3.4
  • JDK 17
  • Gradle 8.6

Example Application

No response

Version

4.3.4

@sdelamo
Copy link
Contributor

sdelamo commented Mar 8, 2024

are you working with API Gateway Urls or with a custom domain? We have a dependency to help you work with API Gateway
https://micronaut-projects.github.io/micronaut-aws/latest/guide/#amazonApiGateway

which I would recommend you to use instead of using context-page.

@dniel
Copy link
Author

dniel commented Mar 8, 2024

we use a custom domain with api mappings.

@dniel
Copy link
Author

dniel commented Mar 8, 2024

tested with the depcrecated "io.micronaut.function.aws.proxy.MicronautLambdaHandler" again, but it didn't change the outcome.

@sdelamo
Copy link
Contributor

sdelamo commented Mar 8, 2024

so, the issue is you use API Gateway with custom domain and you want also to use context-path and it does not work as expected?

@sdelamo sdelamo self-assigned this Mar 8, 2024
@dniel
Copy link
Author

dniel commented Mar 8, 2024

so, the issue is you use API Gateway with custom domain and you want also to use context-path and it does not work as expected?

I absolutely don't want to configure context-path in my lambda, it breaks our code. :)

The issue is, in the Lambda event sent fromthe API Gateway.

  • Micronaut 3 seems to use property "resource" in the lambda event for routing.
  • Micronaut 4 seems to use property "path" in the lambda event for routing.
  • Resource and path does not have the same values, routing breaks when upgrading.
    • API Gateway add the api mapping/context path to "path" property
    • API Gateway does not add api mapping/context path to "resource" property
{
  "path": "/whatever-api/users",
  "resource":  "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}

I want Micronaut to continue use the "resource"-property to evaluate routing so that its possible to add the lambda to whatever custom domain and api-mapping I want, as using "path" which contain the api-mapping from API Gateway "locks" the lambda to be used just in that API..

Reverting to the old behaviour of Micronaut3, with using the resource-property to route incoming request would is prefered and would make the lambda much more reusable between difference API Gateway apis.

@sdelamo
Copy link
Contributor

sdelamo commented Mar 8, 2024

do you have an example of how you are setting API Gateway in console or better in CDK code?

@dniel
Copy link
Author

dniel commented Mar 8, 2024

We are importing the openapi spec from micronaut to create the APIs. I will find an example.

This is how the OpenApi is generated from Micronaut, by adding Extensions for API- Gateway config to the source code.

  /users:
    get:
      operationId: getUsers
      responses:
        "200":
          description: Ok
          content:
            application/json: {}
      security:
      - cognito_auth:
        - https://services.xxxx/users
      x-amazon-apigateway-request-validator:
        x-amazon-apigateway-request-validator: "Validate body, query string parameters,\
          \ and headers"
      x-amazon-apigateway-integration:
        passthroughBehavior: when_no_match
        uri: "${lambda_rest_api_invoke_arn}"
        httpMethod: POST
        type: aws_proxy

Its imported by running terraform with the openapi spec as body, local.schema is just the open-api file.

resource "aws_api_gateway_rest_api" "api_gateway_rest_api" {
  description = "API for Users"
  name        = "users-rest-api"
  body        = local.schema
}

and in addition we create

This will create a api-gateway api https://www.exampe.com/myapp that listens for incoming users request on https://www.exampe.com/myapp/users and invoke our lambda on requests.

Events sent to the lambda will look like this

{
  "path": "/myapp/users",
  "resource":  "/users",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json"
  }
}

It will work in Micronaut 3, but crash in Micronaut 4.

@dniel
Copy link
Author

dniel commented Mar 8, 2024

What class in Micronaut is parsing and handling the evaluation of the incoming Lambda event content?
Especially where it reads the path and resource properties?

@dniel
Copy link
Author

dniel commented May 14, 2024

@nathanthorpe
Copy link

I'm experiencing this issue too, and it seems like a regression from this fix #19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

No branches or pull requests

3 participants