From 00c8d75fadf49547e81b9dda07221796c2076622 Mon Sep 17 00:00:00 2001 From: etorralba Date: Mon, 8 May 2023 17:14:49 -0600 Subject: [PATCH] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20Hosting=20Media=20?= =?UTF-8?q?Handler=20on=20AWS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/docs/reference/media/external/s3.md | 106 ++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/content/docs/reference/media/external/s3.md b/content/docs/reference/media/external/s3.md index 2830a40ee..4f43919d9 100644 --- a/content/docs/reference/media/external/s3.md +++ b/content/docs/reference/media/external/s3.md @@ -157,6 +157,108 @@ export default createMediaHandler({ For Netlify usecase, please read how to set up Netlify Functions [here](/docs/reference/media/external/authentication/#netlify) +### Hosting Media Handler on AWS + +#### **Prerequisites** +`npm install express @vendia/serverless-express @tinacms/auth body-parser` + +#### **Lambda Function** + +1. To connect TinaCMS endpoints to AWS services, you'll need to create a Lambda Function in Node 14.x. Here's the code you'll need: + + ```tsx + # index.ts + import express, { Router } from 'express'; + import serverlessExpress from '@vendia/serverless-express'; + import { isAuthorized } from '@tinacms/auth'; + import { createMediaHandler, + } from "next-tinacms-s3/dist/handlers"; + import bodyParser from 'body-parser'; + + // Configure TinaCMS + const mediaHandler = createMediaHandler({ + config: { + credentials: { + accessKeyId: process.env.TINA_AWS_ACCESS_KEY_ID || "", + secretAccessKey: process.env.TINA_AWS_SECRET_ACCESS_KEY || "", + }, + region: process.env.TINA_AWS_REGION, + }, + bucket: process.env.TINA_AWS_BUCKET_NAME || "", + authorized: async (req, _res): Promise => { + if (process.env.NODE_ENV === "development") { + return true; + } + try { + const user = await isAuthorized(req); + return user && user.verified; + } catch (e) { + console.error(e); + return false; + } + }, + }) + + // Set up the express app and router + const app = express() + const router = Router() + app.use(bodyParser.json()) + + // Define routes for media handling + router.get('/s3/media', mediaHandler) + router.post('/s3/media', mediaHandler) + router.delete("/s3/media/:media", (req, res) => { + req.query.media = ["media", req.params.media]; + return mediaHandler(req, res); + }); + + // Mount the router on the app + app.use('/api/', router) + + // Export the handler function + exports.handler = serverlessExpress({ app}) + + ``` + +2. Be sure to configure the necessary environment variables: + + ```yaml + TINA_AWS_ACCESS_KEY_ID=****************** + TINA_AWS_BUCKET_NAME=****************** + TINA_AWS_REGION=******** + TINA_AWS_SECRET_ACCESS_KEY=****************** + + ``` + + +#### **API Gateway** + +1. With the Lambda Function in place, you can proceed to create an API Gateway: + + 1. Click on **`Create API`** + 2. Select **REST API** +2. Once the API is created, create a resource under the root path named **`/api`** by going to _Resources_ and selecting _Create Resource_ + +3. Next, create a nested child path that takes all **`/api`** child paths by creating a resource that uses the **`{proxy+}`** special syntax. Make sure to tick the **_Configure as proxy resource._** + + When setting up the ANY method, pass the Lambda Function that handles the TinaCMS media manager logic. + + Click on **`save`** and allow API Gateway to add permission to the Lambda Function + +4. Deploy your API by clicking on the _Action_ dropdown and selecting Deploy API + + 1. Select **`[New Stage]`** for the Deployment Stage and type a _Stage name_ + 2. Once the API is deployed, you can see the _Invoke URL_ in the _Stages_ menu by clicking on the stage you've created. +5. Configure **Binary Media Types** by going to the _Settings_ Menu and adding the **`/*`** wildcard + + +#### **CloudFront** + +1. To complete the connection, create a new **Origin** for CloudFront using the _Invocation URL_ of the API Gateway that was just created. Set the Origin Path to the name of the stage where the API was deployed. +2. Create a new **Behaviour** for CloudFront that will intercept requests with the **`/api/s3/media*`** path and use the API Gateway origin that was just created. Make sure to allow the following HTTP methods: **`GET`**, **`HEAD`**, **`OPTIONS`**, **`PUT`**, **`POST`**, **`PATCH`**, and **`DELETE`**. + 1. Under the **Cache key and origin requests** section, select the _Cache policy and origin request policy_ option. For the _Cache policy_, select **CachingDisabled**. For the _Origin request policy_, select **AllViewerExceptHostHeader**. +3. Repeat the above process to create another behaviour that intercepts requests with the **`/api/s3/media/*`** path. + ## Update Schema Now that the media store is registered and the API route for media set up, let's add an image to your schema. @@ -171,4 +273,8 @@ In your schema add a new field for the image, e.g: } ``` + + + + Now, when editing your site, the image field will allow you to connect to your S3 Bucket via the Media Store to manage your media assets.