hono icon indicating copy to clipboard operation
hono copied to clipboard

aws-lambda / HTTP API V2 / broken req.url encoding

Open aheissenberger opened this issue 1 year ago • 6 comments

What version of Hono are you using?

3.12.8

What runtime/platform is your app running on?

AWS Lambda / Node 20 / API Gateway HTTP API V2

What steps can reproduce the bug?

The content of the Hono req.url is wrongly encoded which breaks the url!

Expample POST request: POST /RSC/%40id%2Fassets%2Frsf0.js%23save.txt

wrong Result: req.url: /RSC/@id/assets/rsf0.js#save.txt

What is the expected behavior?

expected: http://localhost/RSC/%40id%2Fassets%2Frsf0.js%23save.txt

What do you see instead?

wrong: http://localhost/RSC/@id/assets/rsf0.js#save.txt

Additional information

The problem stems from the already encoded url rawPath provided by the AWS API Gateway in the JSON Event Format HTTP API V2. This looks like a bug in the API Gateway HTTP API - specific to Version 2.0 Events.

I do not see any way to fix this problem on this layer :-( Encoding the whole path will produce a different broken result - e.g. %2FRSC%2F%40id%2Fassets%2Frsf0.js%23save.txt

Example with API Gateway Event:

import { handle } from 'hono/aws-lambda'
import { Hono } from 'hono'

const app = new Hono()

app.post('*', (c) => {
  return c.text(`c.req.url: "${c.req.url}"`)
})

const handler = handle(app)

// a simplified version of an original AWS API Gateway Event received in an AWS Lambda handler
const postEvent = (path:string)=>({
  version: '2.0',
  routeKey: '$default',
  rawPath: path,
  rawQueryString: '',
  headers: {
    'accept-encoding': 'gzip, deflate, br',
    'content-length': '154',
    'content-type': 'text/plain;charset=UTF-8',
    host: 'yyy.execute-api.us-east-1.amazonaws.com',
    origin: 'https://xxx.cloudfront.net',
    'user-agent': 'Amazon CloudFront'
  },
  requestContext: {
    domainName: 'yyy.execute-api.us-east-1.amazonaws.com',
    domainPrefix: 'yyy',
    http: {
      method: 'POST',
      path: path,
      protocol: 'HTTP/1.1',
      userAgent: 'Amazon CloudFront'
    },
  },
  body: '',
  isBase64Encoded: false
})

const response =await handler(postEvent('/RSC/@id/assets/rsf0.js#save.txt'), {})
console.log(response)

response output:

{
  body: 'c.req.url: "https://yyy.execute-api.us-east-1.amazonaws.com/RSC/@id/assets/rsf0.js#save.txt"',
  headers: { 'content-type': 'text/plain;charset=UTF-8' },
  statusCode: 200,
  isBase64Encoded: false
}

aheissenberger avatar Feb 06 '24 12:02 aheissenberger

Hi @aheissenberger

Thanks for the issue.

@watany-dev Could be a Hono core issue, but can you take a look at this once?

yusukebe avatar Feb 06 '24 12:02 yusukebe

I looked into the adapter: https://github.com/honojs/hono/blob/09845e5e045c9da08c0b2d46a3882ff47ca98e4d/src/adapter/aws-lambda/handler.ts#L200-L202

In line 200 the value from event.rawPath ist used for V2 Events and combined with the domainName in line 202.

This needs to be fixed in the AWS Gateway API but I found no way to raise an issue there and I hope this issue here will help others running into this bug.

aheissenberger avatar Feb 06 '24 12:02 aheissenberger

The best fix until the AWS Gateway provides a fix for rawPath in Version "2.0" is to switch back to Version "1.0". This is possible for specific path and methods.

aheissenberger avatar Feb 06 '24 15:02 aheissenberger

Thank you for raising this issue. Halting support for version 2.0 would be equivalent to discontinuing support for specific patterns of Lambda Functions URLs and API Gateway, which I believe we should not do. We should focus on the paths instead.

watany-dev avatar Feb 07 '24 07:02 watany-dev

Thank you for raising this issue. Halting support for version 2.0 would be equivalent to discontinuing support for specific patterns of Lambda Functions URLs and API Gateway, which I believe we should not do. We should focus on the paths instead.

My tip was not targeting this library. It is an option for people who use this library in their projects as a simple tested workaround for the problem on a specific path in their application.

Regarding continuing support of V2 with this adapter, I 100% agree with you :-)

aheissenberger avatar Feb 07 '24 13:02 aheissenberger

Sorry for the misunderstanding. Your kind sharing of information is wonderful!

watany-dev avatar Feb 07 '24 13:02 watany-dev

@aheissenberger @watany-dev Is this issue is solved?

yusukebe avatar Mar 25 '24 17:03 yusukebe

@aheissenberger @watany-dev Is this issue is solved?

The problem is avoided by using a different url structure which is not impacted by this bug in the AWS api.

aheissenberger avatar Mar 26 '24 01:03 aheissenberger

Thanks! I'll close this issue, but if you have a problem, feel free to reopen it.

yusukebe avatar Apr 09 '24 08:04 yusukebe