sveltekit-adapter-aws icon indicating copy to clipboard operation
sveltekit-adapter-aws copied to clipboard

Handle CloudFront/Function URL named form actions returning 400 because of `/` being invalid

Open willfarrell opened this issue 2 years ago • 5 comments

Is your feature request related to a problem? Please describe. When using CloudFront Origin Request Policies and Lambda Function URL named form action returning 400 because of / is considered invalid

Describe the solution you'd like

  1. Adaptor casts <form method="POST" action="?/anything"> to <form method="POST" action="?%2Fanything">
  2. Adaptor decodes %2F to /

Describe alternatives you've considered

mv ${DIR}/../build/server/index.js ${DIR}/../build/server/index.mjs
sed -i.bak 's|formaction="\?\/|formaction="?%2F|g' ${DIR}/../build/server/index.mjs
sed -i.bak 's|action="\?\/|action="?%2F|g' ${DIR}/../build/server/index.mjs
sed -i.bak 's|action2 = `\?/\${action2}`;|action2 = `?%2F${action2}`;|' ${DIR}/../build/server/index.mjs

and modify adaptor as 2 above

const localeHandler = async ({ event, resolve }) => {
  const response = await resolve(event, {
    transformPageChunk: ({ html }) => {
      // Work around for AWS Lambda Function URL
      if (process.env.AWS_EXECUTION_ENV) {
        html = html.replace(/action="\?\//g, `action="?%2F`)
      }
      return html
    }
  })
  return response
}

Additional context

  • https://github.com/sveltejs/kit/issues/7098
  • https://github.com/sveltejs/kit/issues/9057

cc @CalebBassham

willfarrell avatar Feb 15 '23 17:02 willfarrell

In November, an AWS support rep let me know that this should be fixed for AWS Function URLs by mid January. Evidently, that has not happened.

That was way to long for me, so the solution was to not use Lambda Function URLs. Instead you can use API Gateway which works fine. This solution kinda sucks obviously, but that is what I had to do. Fortunately this project uses API Gateway, so I choose to migrate from my own custom adapter (no aws adapter existed at the time) to this one.

My project also uses CDK, so it was pretty easy to add this project as a dependency and import the stack from here as a part of my stack. However, It does not come without downsides. My project is a monorepo with a relatively small number of packages (~10). Really only two matter for this scenario. One is my CDK package. One is my SvelteKit package. Both must depend on this project and the version must be kept in sync. The CDK package depends on it because it needs the stack that is exports. The SK package depends on it because it needs the adapter. Unfortunately, that is not where the version problems end. The more serious problem I have is the CDK dependencies. CDK projects must depend on aws-cdk-lib and constructs npm packages. Now because I am using the stack from this project in my own, the version of those dependencies must be kept in sync with the version this project is using at the time. Which is 1, a pain, and 2, sort of a problem since this project doesn't have to update super often. But that is not all! CDK also has a CLI which must be kept at the same version as aws-cdk-lib. The kicker is that, as far as I know, none of this is manageable by npm or pnpm. Every time I update the packages of my project now, I must go through this tedious process:

  1. Make sure both my SK and CDK packages updated to the same version of sveltekit-adapter-aws
  2. Check what version of aws-cdk-lib and constructs that sveltekit-adapter-aws is using. Update my aws-cdk-lib and constructs to use the same version.
  3. Update the CLI (aws-cdk) to be the same version as aws-cdk-lib

It is not the worst process to go through, but it is not convenient. However, I am willing to go through it since I no longer have to maintain an AWS adapter on my own which was much less fun. It is something that could probably be automated with a script somewhat easily.

This is probably way more information than you were asking for, but you also didn't really ask a question. I figured I would just give an update on what I have done since my last post.

CalebBassham avatar Feb 15 '23 20:02 CalebBassham

@CalebBassham Thanks for sharing! I use terraform for everything and was hoping to avoid using APIG for simplicity. AWS SecurityHub has also been complaining the Lambda using Function URL for having authorization=NONE.

willfarrell avatar Feb 15 '23 20:02 willfarrell

Yea, it seems that Function URLs work OK for something "quick and dirty," but a lot of cracks start to show once you dive in a little bit. Hopefully they can get it worked out because it is really convenient compared to APIG for single handler applications.

CalebBassham avatar Feb 15 '23 20:02 CalebBassham

Something I noted to AWS was that your can't whitelist query strings with / or ~ (not url encoded) into the CloudFront origin request policy, indicating it might not just be function urls.

willfarrell avatar Feb 15 '23 21:02 willfarrell

Interesting, CloudFront will handle it just fine though if there is a query string with / that passes through.

CalebBassham avatar Feb 15 '23 21:02 CalebBassham