소스 검색

Bucket fn also remote files (#4693)

* support `bucket` fn also for remote files

currently it gives an error if passed a function (something like cannot call split on a function)

* rename priv methods

* Update packages/@uppy/companion/src/server/helpers/utils.js

Co-authored-by: Antoine du Hamel <antoine@transloadit.com>

---------

Co-authored-by: Antoine du Hamel <antoine@transloadit.com>
Mikael Finstad 1 년 전
부모
커밋
e9f335cbe6

+ 8 - 8
packages/@uppy/companion/src/server/Uploader.js

@@ -12,7 +12,7 @@ const throttle = require('lodash/throttle')
 
 const { Upload } = require('@aws-sdk/lib-storage')
 
-const { rfc2047EncodeMetadata } = require('./helpers/utils')
+const { rfc2047EncodeMetadata, getBucket } = require('./helpers/utils')
 
 // TODO move to `require('streams/promises').pipeline` when dropping support for Node.js 14.x.
 const pipeline = promisify(pipelineCb)
@@ -218,11 +218,11 @@ class Uploader {
 
     switch (protocol) {
       case PROTOCOLS.multipart:
-        return this._uploadMultipart(this.readStream)
+        return this.#uploadMultipart(this.readStream)
       case PROTOCOLS.s3Multipart:
-        return this._uploadS3Multipart(this.readStream)
+        return this.#uploadS3Multipart(this.readStream)
       case PROTOCOLS.tus:
-        return this._uploadTus(this.readStream)
+        return this.#uploadTus(this.readStream)
       default:
         throw new Error('Invalid protocol')
     }
@@ -502,7 +502,7 @@ class Uploader {
    *
    * @param {any} stream
    */
-  async _uploadTus (stream) {
+  async #uploadTus (stream) {
     const uploader = this
 
     const isFileStream = stream instanceof ReadStream
@@ -564,7 +564,7 @@ class Uploader {
     })
   }
 
-  async _uploadMultipart (stream) {
+  async #uploadMultipart (stream) {
     if (!this.options.endpoint) {
       throw new Error('No multipart endpoint set')
     }
@@ -642,7 +642,7 @@ class Uploader {
   /**
    * Upload the file to S3 using a Multipart upload.
    */
-  async _uploadS3Multipart (stream) {
+  async #uploadS3Multipart (stream) {
     if (!this.options.s3) {
       throw new Error('The S3 client is not configured on this companion instance.')
     }
@@ -655,7 +655,7 @@ class Uploader {
     const { client, options } = s3Options
 
     const params = {
-      Bucket: options.bucket,
+      Bucket: getBucket(options.bucket),
       Key: options.getKey(null, filename, this.options.metadata),
       ContentType: this.options.metadata.type,
       Metadata: rfc2047EncodeMetadata(this.options.metadata),

+ 8 - 18
packages/@uppy/companion/src/server/controllers/s3.js

@@ -14,7 +14,7 @@ const {
 const { createPresignedPost } = require('@aws-sdk/s3-presigned-post')
 const { getSignedUrl } = require('@aws-sdk/s3-request-presigner')
 
-const { rfc2047EncodeMetadata } = require('../helpers/utils')
+const { rfc2047EncodeMetadata, getBucket } = require('../helpers/utils')
 
 module.exports = function s3 (config) {
   if (typeof config.acl !== 'string' && config.acl != null) {
@@ -24,16 +24,6 @@ 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}
@@ -62,7 +52,7 @@ module.exports = function s3 (config) {
     const client = getS3Client(req, res)
     if (!client) return
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     const metadata = req.query.metadata || {}
     const key = config.getKey(req, req.query.filename, metadata)
@@ -126,7 +116,7 @@ module.exports = function s3 (config) {
       res.status(400).json({ error: 's3: content type must be a string' })
       return
     }
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     const params = {
       Bucket: bucket,
@@ -170,7 +160,7 @@ module.exports = function s3 (config) {
       return
     }
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     const parts = []
 
@@ -221,7 +211,7 @@ module.exports = function s3 (config) {
       return
     }
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     getSignedUrl(client, new UploadPartCommand({
       Bucket: bucket,
@@ -270,7 +260,7 @@ module.exports = function s3 (config) {
       return
     }
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     Promise.all(
       partNumbersArray.map((partNumber) => {
@@ -313,7 +303,7 @@ module.exports = function s3 (config) {
       return
     }
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     client.send(new AbortMultipartUploadCommand({
       Bucket: bucket,
@@ -354,7 +344,7 @@ module.exports = function s3 (config) {
       return
     }
 
-    const bucket = getBucket(req)
+    const bucket = getBucket(config.bucket, req)
 
     client.send(new CompleteMultipartUploadCommand({
       Bucket: bucket,

+ 10 - 0
packages/@uppy/companion/src/server/helpers/utils.js

@@ -186,3 +186,13 @@ const rfc2047Encode = (dataIn) => {
 module.exports.rfc2047EncodeMetadata = (metadata) => (
   Object.fromEntries(Object.entries(metadata).map((entry) => entry.map(rfc2047Encode)))
 )
+
+module.exports.getBucket = (bucketOrFn, req) => {
+  const bucket = typeof bucketOrFn === 'function' ? bucketOrFn(req) : bucketOrFn
+
+  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
+}