unjs / nitro

Next Generation Server Toolkit. Create web servers with everything you need and deploy them wherever you prefer.
https://nitro.unjs.io
MIT License
5.82k stars 491 forks source link

aws lambda-edge #79

Open pi0 opened 2 years ago

pi0 commented 2 years ago

https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html

https://github.com/nuxt/nuxt.js/issues/11700

tresko commented 2 years ago

Hi, I wonder if you have any ETA for this preset?

WinterYukky commented 2 years ago

@tresko I created the PR exactly at the moment you commented. LOL!

The current escape hatch is to wrap an existing preset for Lambda@Edge. An example of wrapping a aws-lambda preset is shown in the following code.

import { URLSearchParams } from "url";
import * as nitro from "./index.mjs";

export const handler = async (event) => {
  const request = event.Records[0].cf.request;
  const queryStringParameters = Object.fromEntries(
    new URLSearchParams(request.querystring).entries()
  );

  const response = await nitro.handler({
    path: request.uri,
    queryStringParameters,
    httpMethod: request.method,
    headers: normalizeIncomingHeaders(request.headers),
    body: request.body,
  });
  return {
    status: response.statusCode,
    headers: normalizeOutgoingHeaders(response.headers),
    body: response.body,
  };
};

function normalizeIncomingHeaders(headers) {
  return Object.fromEntries(
    Object.entries(headers).map(([key, keyValues]) => [
      key,
      keyValues.map((kv) => kv.value).join(","),
    ])
  );
}
function normalizeOutgoingHeaders(headers) {
  return Object.fromEntries(
    Object.entries(headers).map(([key, values]) => [
      key,
      values.split(",").map((value) => ({ value })),
    ])
  );
}

Saving this code as wrapper.mjs and setting the Lambda entry point as wrapper.handler should work. NOTE: require nodejs_14_x or nodejs_16_x

tresko commented 2 years ago

@WinterYukky Wow, amazing! Thank you!

I saw on your PR that you are using Nuxt3 on lambda@edge. Am I correct?

Can you share a wrapper example for Nuxt 3?

WinterYukky commented 2 years ago

@tresko Yes. I'm using Nuxt3 on lambda@edge.

I have created and published a simple project for you. It is a site that when accessed via /<anime title> calls free API and SSR the results. The AWS configuration is written by AWS CDK in the cdk directory. I have included a few comments as you may not be familiar with the AWS CDK, but if you have any questions please ask.

I have included the deployment procedure at the end of README.md so you can try it if you like.

ref: https://github.com/WinterYukky/nuxt3-lambda-edge-example

tresko commented 2 years ago

@WinterYukky Thank you!

anjali89r commented 1 year ago

@pi0 any plan to support this feature in the near future?

ennioVisco commented 1 year ago

Up, there are currently two PRs for this. It is very frustrating that @pi0 is not explaining why/what was wrong with the first one/ what are the technical difficulties/ what are higher priorities 😢

Hebilicious commented 1 year ago

There's 2 PR Open for lambda-edge, but they are not the same.

We could create 2 different presets, lambda-edge and lambda-edge-cdk

https://github.com/unjs/nitro/pull/1075 => lambda-edge https://github.com/unjs/nitro/pull/240 => lambda-edge-cdk

Both preset should use the same entry for the runtime.

There's also the option to have a single preset and a config flag such as aws-lambda-edge.cdk = true

The CDK version is useful for direct deploy, see here https://github.com/unjs/nitro/issues/1387

The non cdk version is useful to integrate with IAC deployment frameworks such as SST, Pulumi etc

Tracked in Nitro : https://github.com/unjs/nitro/issues/133 SST issue for Nuxt: https://github.com/serverless-stack/sst/issues/2314 SST PR for Nuxt support : https://github.com/serverless-stack/sst/pull/2989 Working demo SST+Nuxt+lambda-edge: https://github.com/jdevdevdev/nuxt-sst/blob/lambda-edge/nuxt-app/server/nitro/preset/entry.ts

AlbertSabate commented 8 months ago

Hello, I can see that this development has been stopped for a while. Is there any intention to finish it? I wanted to submit a PR for this, but there are many of them already. If anybody wants a working solution based on the current opened PRs, you can use it from my fork:

"nitropack": "git://github.com/AlbertSabate/nitro#df9eed697da2d7f09fa9a4a4f9d008fe11201df1" -> Updated to current v2.8.1 And then use the preset: preset: 'aws-lambda-edge',.

Let me know if I can help speed this up to have it on the official repo. But, for now, I won't submit anything as the credits should go for the already opened ones.

Hebilicious commented 8 months ago

Hello, I can see that this development has been stopped for a while. Is there any intention to finish it? I wanted to submit a PR for this, but there are many of them already. If anybody wants a working solution based on the current opened PRs, you can use it from my fork:

"nitropack": "git://github.com/AlbertSabate/nitro#df9eed697da2d7f09fa9a4a4f9d008fe11201df1" -> Updated to current v2.8.1 And then use the preset: preset: 'aws-lambda-edge',.

Let me know if I can help speed this up to have it on the official repo. But, for now, I won't submit anything as the credits should go for the already opened ones.

I think this hasn't been reviewed yet because it's low on the priority list. I left comments for @pi0 in #1557 about the 2 possible approaches. However I'm pretty sure SST has evolved since, so we would need to pin the compatible versions. An approach like #1075 would be easier to review and merged in, but that wouldn't be deployable by Nitro alone.

AlbertSabate commented 8 months ago

Hello @Hebilicious,

I have reviewed both PRs, and it will be very easy to get merged #1075; there are a few lines that need to be updated to make it work with the latest nitro version. After merging this, you can finish branch #1557, which seems way more complicated and, as you said, may need to be updated.

For example, in my case, I use it to build a Solidjs app. In the new version 0.4.2, they have implemented Vinxi, which uses nitropack to build a solidjs app. Then I have my own CDK deployment script. So, having #1075 will be plug-and-play, while #1557 is irrelevant for my use case. This is an example. I'd be very happy to share my CDK script with you if that helps you finish #1557, but from what I see, the bottleneck comes from SST.

My opinion on the matter: Step 1: Prepare and merge #1075. I can help you if necessary Step 2: Finish and merge the CDK as a separate preset since it is almost done. I can also give you a hand with this. This could make use of the previous handler. Step 3: SST: I need help understanding this point, as SST already provides everything for deploying an app. But it can come from step 3 because it can make a gain of the handler of step 1 and base the resource creation based on step 2.

Having those three split may seem too much preset, but it will be clear, as my understanding.

Let me know if you want me to help with anything! :)