fastify / aws-lambda-fastify

Insipired by aws-serverless-express to work with Fastify with inject functionality.
MIT License
501 stars 32 forks source link

url encode/decode problem #169

Closed andyli closed 1 year ago

andyli commented 1 year ago

Prerequisites

Fastify version

4.21.0

Plugin version

3.3.0

Node.js version

18.x

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.6.7

Description

The fastify app running locally and the same app deployed to aws lambda handle escaped url paths differently.

For example, in http://localhost:3000/a%2Fb, request.url would be /a%2Fb. However, https://xxxxx.amazonaws.com/a%2Fb,request.url would be /a/b.

Steps to Reproduce

Here is a minimal working example: https://github.com/andyli/test-fastify-aws-lambda-url

Expected Behavior

The same app running locally and in aws lambda would give the same request.url.

adrai commented 1 year ago

Can you paste the incoming lambda event? I suspect this is done because of AWS... https://stackoverflow.com/questions/69677023/aws-api-gateway-expects-the-request-url-to-be-encoded-twice

andyli commented 1 year ago

For https://ijkudl15ye.execute-api.us-east-1.amazonaws.com/a%2Fb

request.url: /a/b

request.awsLambda.event:
{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/a/b",
    "rawQueryString": "",
    "headers": {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "en-GB,en-US;q=0.9,en;q=0.8,zh-HK;q=0.7,zh;q=0.6,zh-TW;q=0.5",
        "content-length": "0",
        "host": "ijkudl15ye.execute-api.us-east-1.amazonaws.com",
        "sec-ch-ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"macOS\"",
        "sec-fetch-dest": "document",
        "sec-fetch-mode": "navigate",
        "sec-fetch-site": "none",
        "sec-fetch-user": "?1",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
        "x-amzn-trace-id": "Root=1-64d775e1-5d07021d014672a36deb7b52",
        "x-forwarded-for": "193.178.112.247",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "requestContext": {
        "accountId": "932878902707",
        "apiId": "ijkudl15ye",
        "domainName": "ijkudl15ye.execute-api.us-east-1.amazonaws.com",
        "domainPrefix": "ijkudl15ye",
        "http": {
            "method": "GET",
            "path": "/a/b",
            "protocol": "HTTP/1.1",
            "sourceIp": "193.178.112.247",
            "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
        },
        "requestId": "Ji9bWib-IAMEPhQ=",
        "routeKey": "$default",
        "stage": "$default",
        "time": "12/Aug/2023:12:06:57 +0000",
        "timeEpoch": 1691842017935
    },
    "isBase64Encoded": false,
    "body": ""
}

For https://ijkudl15ye.execute-api.us-east-1.amazonaws.com/a/b

request.url: /a/b

request.awsLambda.event:
{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/a/b",
    "rawQueryString": "",
    "headers": {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "en-GB,en-US;q=0.9,en;q=0.8,zh-HK;q=0.7,zh;q=0.6,zh-TW;q=0.5",
        "content-length": "0",
        "host": "ijkudl15ye.execute-api.us-east-1.amazonaws.com",
        "sec-ch-ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"macOS\"",
        "sec-fetch-dest": "document",
        "sec-fetch-mode": "navigate",
        "sec-fetch-site": "none",
        "sec-fetch-user": "?1",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
        "x-amzn-trace-id": "Root=1-64d77637-5603b6e75592afab7564d192",
        "x-forwarded-for": "193.178.112.247",
        "x-forwarded-port": "443",
        "x-forwarded-proto": "https"
    },
    "requestContext": {
        "accountId": "932878902707",
        "apiId": "ijkudl15ye",
        "domainName": "ijkudl15ye.execute-api.us-east-1.amazonaws.com",
        "domainPrefix": "ijkudl15ye",
        "http": {
            "method": "GET",
            "path": "/a/b",
            "protocol": "HTTP/1.1",
            "sourceIp": "193.178.112.247",
            "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
        },
        "requestId": "Ji9osjJBIAMEPJQ=",
        "routeKey": "$default",
        "stage": "$default",
        "time": "12/Aug/2023:12:08:23 +0000",
        "timeEpoch": 1691842103334
    },
    "isBase64Encoded": false,
    "body": ""
}

They have the same rawPath.

adrai commented 1 year ago

exactly... this is all done by aws... sorry. There's not much we can do here.

andyli commented 1 year ago

That's unfortunate.

I've found a workaround in your SO link though. That's to use API Gateway v1 REST API instead of the v2 HTTP API.

i.e.

    # events:
    #   - httpApi: '*'

    events:
      - http:
          method: ANY
          path: '/'
      - http:
          method: ANY
          path: '{proxy+}'

Thanks!