From 69e1d484557e11b6ca62538a815b7b17c6be540b Mon Sep 17 00:00:00 2001 From: Richard Bradley Date: Mon, 15 Aug 2022 21:06:50 +0100 Subject: [PATCH 1/4] Add support for ${filename} in POST Object --- lib/controllers/object.js | 3 ++- test/controllers/object.spec.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/controllers/object.js b/lib/controllers/object.js index b4acc48f..2d104684 100644 --- a/lib/controllers/object.js +++ b/lib/controllers/object.js @@ -313,10 +313,11 @@ exports.postObject = async function postObject(ctx) { break; } }; - const fileHandler = (fieldname, file) => { + const fileHandler = (fieldname, file, filename) => { if (fieldname !== 'file' || fileCount++) { return file.resume(); } + key = key.replace('${filename}', filename); resolve(new S3Object(ctx.params.bucket, key, file, metadata)); }; diff --git a/test/controllers/object.spec.js b/test/controllers/object.spec.js index a669e61e..c2276ee1 100644 --- a/test/controllers/object.spec.js +++ b/test/controllers/object.spec.js @@ -378,7 +378,7 @@ describe('Operations on Objects', () => { describe('POST Object', () => { it('stores a text object for a multipart/form-data request', async function () { const form = new FormData(); - form.append('key', 'text'); + form.append('key', 'my_files/${filename}'); form.append('file', 'Hello!', 'post_file.txt'); const res = await request.post('bucket-a', { baseUrl: s3Client.endpoint.href, @@ -387,7 +387,7 @@ describe('Operations on Objects', () => { }); expect(res.statusCode).to.equal(204); const object = await s3Client - .getObject({ Bucket: 'bucket-a', Key: 'text' }) + .getObject({ Bucket: 'bucket-a', Key: 'my_files/post_file.txt' }) .promise(); expect(object.ContentType).to.equal('binary/octet-stream'); expect(object.Body).to.deep.equal(Buffer.from('Hello!')); From 568fce181f3308596e3ce59238650788f9ba840b Mon Sep 17 00:00:00 2001 From: Richard Bradley Date: Mon, 6 Nov 2023 13:59:14 +0000 Subject: [PATCH 2/4] Suppress eslint false positive --- lib/controllers/object.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/controllers/object.js b/lib/controllers/object.js index 2d104684..544e0abb 100644 --- a/lib/controllers/object.js +++ b/lib/controllers/object.js @@ -317,6 +317,7 @@ exports.postObject = async function postObject(ctx) { if (fieldname !== 'file' || fileCount++) { return file.resume(); } + // eslint-disable-next-line no-template-curly-in-string key = key.replace('${filename}', filename); resolve(new S3Object(ctx.params.bucket, key, file, metadata)); }; From 9d7c9a0d517dac8e36dd5389f641df82ca0f1e40 Mon Sep 17 00:00:00 2001 From: Richard Bradley Date: Mon, 6 Nov 2023 13:59:33 +0000 Subject: [PATCH 3/4] ${filename} in POST Object should strip leading spaces --- lib/controllers/object.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/controllers/object.js b/lib/controllers/object.js index 544e0abb..8bad35d4 100644 --- a/lib/controllers/object.js +++ b/lib/controllers/object.js @@ -317,8 +317,10 @@ exports.postObject = async function postObject(ctx) { if (fieldname !== 'file' || fileCount++) { return file.resume(); } + // S3 strips leading spaces from filename here, even though their docs + // don't mention it. I have raised this as an issue with AWS Enterprise support // eslint-disable-next-line no-template-curly-in-string - key = key.replace('${filename}', filename); + key = key.replace('${filename}', filename.replace(/^ +/, '')); resolve(new S3Object(ctx.params.bucket, key, file, metadata)); }; From aed17c2779abced26b746a62021c3e8dbe248a25 Mon Sep 17 00:00:00 2001 From: Richard Bradley Date: Thu, 25 Jan 2024 12:12:06 +0000 Subject: [PATCH 4/4] Key needs url escaping in Location header in upload response --- lib/controllers/object.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/controllers/object.js b/lib/controllers/object.js index 8bad35d4..4db1edd7 100644 --- a/lib/controllers/object.js +++ b/lib/controllers/object.js @@ -410,7 +410,7 @@ exports.postObject = async function postObject(ctx) { if (!location.pathname.endsWith('/')) { location.pathname += '/'; } - location.pathname += object.key; + location.pathname += encodeURIComponent(object.key); ctx.set('Location', location.href); }