Skip to content

Conversation

svozza
Copy link
Contributor

@svozza svozza commented Aug 16, 2025

Summary

This PR implements the final resolution logic for the BaseRouter class. The resolve method is no longer abstract and has a concrete implementation where it looks up the route registry using the path and tries to retirve a resolver for the route. If not route is found, we throw a NotFoundErroe. If any exceptions are thrown from the handler, these are caught and handled by the already existing handleError method.

Changes

  • Update BaseRouter to have. oncrete implementation of resolve method
  • Added new conversion functions to produce the APIGatewayProxyResult type that lambda expects
  • Updated the unit tests now that the resolve function is implemented in the base class
  • Added tests to ensure this context is preserved when using decorators.

Issue number: closes #4142


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Disclaimer: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful.

@svozza svozza added this to the Event Handler Beta (priority) milestone Aug 16, 2025
@svozza svozza requested a review from dreamorosi August 16, 2025 16:38
@svozza svozza self-assigned this Aug 16, 2025
@pull-request-size pull-request-size bot added the size/XXL PRs with 1K+ LOC, largely documentation related label Aug 16, 2025
@boring-cyborg boring-cyborg bot added event-handler This item relates to the Event Handler Utility tests PRs that add or change tests labels Aug 16, 2025
@svozza svozza force-pushed the event-handler/response-resolver-logic branch from f5d5280 to 14a6f53 Compare August 17, 2025 19:12
@svozza svozza force-pushed the event-handler/response-resolver-logic branch from 14a6f53 to 7a9b621 Compare August 18, 2025 10:31
Copy link
Contributor

@dreamorosi dreamorosi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we added this in a previous PR, but after testing the BaseRouter in a Lambda function behind API Gateway REST I think I found a bug in the proxyEventToWebRequest function.

Specifically, the headers parsing (below), is problematic as it concatenates values if the same header is present in both headers and multiValueHeaders - which seems to be always the case in my tests:

for (const [name, value] of Object.entries(event.headers ?? {})) {
  if (value != null) headers.append(name, value);
}

for (const [name, values] of Object.entries(event.multiValueHeaders ?? {})) {
  for (const value of values ?? []) {
    headers.append(name, value);
  }
}

For example this request payload (shortened for brevity):

{
  "resource": "/",
  "path": "/",
  "httpMethod": "GET",
  "headers": {
    "Host": "abcd1234.execute-api.eu-west-1.amazonaws.com",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "Host": ["abcd1234.execute-api.eu-west-1.amazonaws.com"],
    "X-Forwarded-Proto": ["https"]
  },
  "queryStringParameters": null,
  "multiValueQueryStringParameters": null,
  "pathParameters": null,
  "stageVariables": null,
  "requestContext": { ... },
    "domainName": "abcd1234.execute-api.eu-west-1.amazonaws.com",
    "deploymentId": "abcd123",
    "apiId": "abcd1234"
  },
  "body": null,
  "isBase64Encoded": false
}

results in this:

console.log(headers.get('Host'));
// abcd1234.execute-api.eu-west-1.amazonaws.com, abcd1234.execute-api.eu-west-1.amazonaws.com 
console.log(headers.get('X-Forwarded-Proto'));
// https, https

making the URL parsing at L40 fail together with the request.

Additionally, like in this case, the proxyEventToWebRequest function is called and run twice both when first parsing the request and then again in the except block when trying to run the handleError - is there any way that we can run it only once?

Another thing I noticed is that when using API Gateway REST, the requestContext.path field includes the stage as path prefix, for example in a stage prod making a request to stuff would result in "path":"/prod/stuff".

Do we expect customers to have to set it in as prefix at the router level, or in their route handlers? Should we instead just use the top level path and resource fields which in this case would be respectively /stuff and /?

@svozza svozza force-pushed the event-handler/response-resolver-logic branch from 9bdb0f4 to 17ae585 Compare August 25, 2025 12:23
@svozza
Copy link
Contributor Author

svozza commented Aug 25, 2025

I know we added this in a previous PR, but after testing the BaseRouter in a Lambda function behind API Gateway REST I think I found a bug in the proxyEventToWebRequest function.

Specifically, the headers parsing (below), is problematic as it concatenates values if the same header is present in both headers and multiValueHeaders - which seems to be always the case in my tests:

I've added logic to check whether the header already includes a value before we append it.

Additionally, like in this case, the proxyEventToWebRequest function is called and run twice both when first parsing the request and then again in the except block when trying to run the handleError - is there any way that we can run it only once?

I've moved the creation of the Request object out of the try/catch handler so we now only do it once.

Another thing I noticed is that when using API Gateway REST, the requestContext.path field includes the stage as path prefix, for example in a stage prod making a request to stuff would result in "path":"/prod/stuff".

Do we expect customers to have to set it in as prefix at the router level, or in their route handlers? Should we instead just use the top level path and resource fields which in this case would be respectively /stuff and /?

Agreed, I've changed it to use the top level fields instead.

@svozza svozza requested a review from dreamorosi August 25, 2025 16:03
Copy link

@dreamorosi dreamorosi merged commit f1ecc6d into main Aug 26, 2025
38 checks passed
@dreamorosi dreamorosi deleted the event-handler/response-resolver-logic branch August 26, 2025 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
event-handler This item relates to the Event Handler Utility size/XXL PRs with 1K+ LOC, largely documentation related tests PRs that add or change tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Implement Response Handling Architecture for Event Handler
3 participants