Skip to content

Commit

Permalink
@uppy/companion: allow dynamic S3 bucket (#4579)
Browse files Browse the repository at this point in the history
* uppy upload s3 controller getBucket function

* Simplify

---------

Co-authored-by: Ricardo Moura <ricardo.moura@lunajets.com>
Co-authored-by: Mikael Finstad <finstaden@gmail.com>
  • Loading branch information
3 people authored Jul 31, 2023
1 parent 9d49a22 commit f639a67
Showing 1 changed file with 58 additions and 39 deletions.
97 changes: 58 additions & 39 deletions packages/@uppy/companion/src/server/controllers/s3.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ module.exports = function s3 (config) {
throw new TypeError('s3: The `getKey` option must be a function')
}

function getBucket (req) {
const bucket = typeof config.bucket === 'function' ? config.bucket(req) : config.bucket

if (!(typeof bucket === 'string' && bucket !== '')) {
// This means a misconfiguration or bug
throw new TypeError('s3: bucket key must be a string or a function resolving the bucket string')
}
return bucket
}

function getS3Client (req, res) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
if (!client) res.status(400).json({ error: 'This Companion server does not support uploading to S3' })
return client
}

/**
* Get upload paramaters for a simple direct upload.
*
Expand All @@ -46,15 +65,10 @@ module.exports = function s3 (config) {
* - fields - Form fields to send along.
*/
function getUploadParameters (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

if (!client || typeof config.bucket !== 'string') {
res.status(400).json({ error: 'This Companion server does not support uploading to S3' })
return
}
const bucket = getBucket(req)

const metadata = req.query.metadata || {}
const key = config.getKey(req, req.query.filename, metadata)
Expand All @@ -75,7 +89,7 @@ module.exports = function s3 (config) {
})

createPresignedPost(client, {
Bucket: config.bucket,
Bucket: bucket,
Expires: config.expires,
Fields: fields,
Conditions: config.conditions,
Expand Down Expand Up @@ -105,10 +119,9 @@ module.exports = function s3 (config) {
* - uploadId - The ID of this multipart upload, to be used in later requests.
*/
function createMultipartUpload (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const key = config.getKey(req, req.body.filename, req.body.metadata || {})
const { type, metadata } = req.body
if (typeof key !== 'string') {
Expand All @@ -119,9 +132,10 @@ module.exports = function s3 (config) {
res.status(400).json({ error: 's3: content type must be a string' })
return
}
const bucket = getBucket(req)

const params = {
Bucket: config.bucket,
Bucket: bucket,
Key: key,
ContentType: type,
Metadata: Object.fromEntries(Object.entries(metadata).map(entry => entry.map(rfc2047Encode))),
Expand Down Expand Up @@ -151,10 +165,9 @@ module.exports = function s3 (config) {
* - Size - size of this part.
*/
function getUploadedParts (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const { uploadId } = req.params
const { key } = req.query

Expand All @@ -163,11 +176,13 @@ module.exports = function s3 (config) {
return
}

const bucket = getBucket(req)

const parts = []

function listPartsPage (startAt) {
client.send(new ListPartsCommand({
Bucket: config.bucket,
Bucket: bucket,
Key: key,
UploadId: uploadId,
PartNumberMarker: startAt,
Expand Down Expand Up @@ -197,10 +212,9 @@ module.exports = function s3 (config) {
* - url - The URL to upload to, including signed query parameters.
*/
function signPartUpload (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const { uploadId, partNumber } = req.params
const { key } = req.query

Expand All @@ -213,8 +227,10 @@ module.exports = function s3 (config) {
return
}

const bucket = getBucket(req)

getSignedUrl(client, new UploadPartCommand({
Bucket: config.bucket,
Bucket: bucket,
Key: key,
UploadId: uploadId,
PartNumber: partNumber,
Expand All @@ -238,10 +254,9 @@ module.exports = function s3 (config) {
* in an object mapped to part numbers.
*/
function batchSignPartsUpload (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const { uploadId } = req.params
const { key, partNumbers } = req.query

Expand All @@ -261,10 +276,12 @@ module.exports = function s3 (config) {
return
}

const bucket = getBucket(req)

Promise.all(
partNumbersArray.map((partNumber) => {
return getSignedUrl(client, new UploadPartCommand({
Bucket: config.bucket,
Bucket: bucket,
Key: key,
UploadId: uploadId,
PartNumber: Number(partNumber),
Expand All @@ -291,10 +308,9 @@ module.exports = function s3 (config) {
* Empty.
*/
function abortMultipartUpload (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const { uploadId } = req.params
const { key } = req.query

Expand All @@ -303,8 +319,10 @@ module.exports = function s3 (config) {
return
}

const bucket = getBucket(req)

client.send(new AbortMultipartUploadCommand({
Bucket: config.bucket,
Bucket: bucket,
Key: key,
UploadId: uploadId,
})).then(() => res.json({}), next)
Expand All @@ -323,10 +341,9 @@ module.exports = function s3 (config) {
* - location - The full URL to the object in the S3 bucket.
*/
function completeMultipartUpload (req, res, next) {
/**
* @type {import('@aws-sdk/client-s3').S3Client}
*/
const client = req.companion.s3Client
const client = getS3Client(req, res)
if (!client) return

const { uploadId } = req.params
const { key } = req.query
const { parts } = req.body
Expand All @@ -343,8 +360,10 @@ module.exports = function s3 (config) {
return
}

const bucket = getBucket(req)

client.send(new CompleteMultipartUploadCommand({
Bucket: config.bucket,
Bucket: bucket,
Key: key,
UploadId: uploadId,
MultipartUpload: {
Expand Down

0 comments on commit f639a67

Please sign in to comment.