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

Adding Dynamic bucket & region params to config #169

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
28 changes: 28 additions & 0 deletions packages/docs-site/src/pages/bucket-config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,31 @@ export default APIRoute.configure({
```

Now your upload will work with any S3 compatible web host.

## Dynamic Bucket configuration

Bucket configuration can be dynamic based on request data.
This is useful if you want to upload files to different buckets in the same AWS account depending on the request or some other criteria.

Warning: We recommend not using this feature to set bucket name via Request body as that could lead to security issues.
Instead, ensure the bucket name is still set from predicated values within the function.

```js
// pages/api/s3-upload.js
import { APIRoute } from "next-s3-upload";

export default APIRoute.configure({
// ..
async bucketName(req) {
const { uploadType } = req.body;
const bucket =
uploadType === S3UploadType.public
? process.env.S3_PUBLIC_BUCKET
: process.env.S3_PRIVATE_BUCKET;

// May extend to more options
return bucket;
},
});
```

16 changes: 13 additions & 3 deletions packages/next-s3-upload/src/backend/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type AppOrPagesRequest = NextApiRequest | NextRequest;

export type Options<R extends AppOrPagesRequest> = S3Config & {
key?: (req: R, filename: string) => string | Promise<string>;
bucketName?: (req: R, filename?: string) => string | Promise<string>;
regionName?: (req: R, filename?: string) => string | Promise<string>;
};

export async function handler<R extends NextApiRequest | NextRequest>({
Expand All @@ -41,7 +43,14 @@ export async function handler<R extends NextApiRequest | NextRequest>({
: `next-s3-uploads/${uuid()}/${sanitizeKey(filename)}`;

const uploadType = body._nextS3?.strategy;
const { bucket, region, endpoint } = s3Config;

const bucket = options.bucketName
? await Promise.resolve(options.bucketName(request, filename))
: s3Config.bucket;

const region = options.regionName
? await Promise.resolve(options.regionName(request, filename))
: s3Config.region;

if (uploadType === 'presigned') {
let { filetype } = body;
Expand All @@ -61,7 +70,7 @@ export async function handler<R extends NextApiRequest | NextRequest>({
key,
bucket,
region,
endpoint,
endpoint: s3Config.endpoint,
url,
};
} else {
Expand Down Expand Up @@ -106,5 +115,6 @@ export async function handler<R extends NextApiRequest | NextRequest>({
const missingEnvs = (config: Record<string, any>): string[] => {
const required = ['accessKeyId', 'secretAccessKey', 'bucket', 'region'];

return required.filter(key => !config[key] || config.key === '');
return required.filter((key) => !config[key] || config.key === '');
};