Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: ✏️ Hosting Media Handler on AWS #1555

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions content/docs/reference/media/external/s3.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,109 @@ 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<any> => {
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.

### Using a Custom URL

If you're using a custom URL for your S3 bucket, you can pass in a `cdnUrl` value to `createMediaHandler`.
Expand All @@ -173,6 +276,7 @@ export default createMediaHandler({
)
```


## 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.
Expand Down
Loading