Skip to content

Commit c2681b8

Browse files
authored
fix: allow creating folders even if the mime type validation is set (#509)
1 parent 6dda887 commit c2681b8

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

src/storage/limits.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,7 @@ export function parseFileSizeToBytes(valueWithUnit: string) {
115115
export function isUuid(value: string) {
116116
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)
117117
}
118+
119+
export function isEmptyFolder(object: string) {
120+
return object.endsWith('.emptyFolderPlaceholder')
121+
}

src/storage/uploader.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ERRORS } from '@internal/errors'
55
import { FileUploadedSuccess, FileUploadStarted } from '@internal/monitoring/metrics'
66

77
import { ObjectMetadata, StorageBackendAdapter } from './backend'
8-
import { getFileSizeLimit } from './limits'
8+
import { getFileSizeLimit, isEmptyFolder } from './limits'
99
import { Database } from './database'
1010
import { ObjectAdminDelete, ObjectCreatedPostEvent, ObjectCreatedPutEvent } from './events'
1111
import { getConfig } from '../config'
@@ -81,10 +81,15 @@ export class Uploader {
8181
async upload(request: FastifyRequest, options: UploaderOptions) {
8282
const version = await this.prepareUpload(options)
8383

84+
// When is an empty folder we restrict it to 0 bytes
85+
if (isEmptyFolder(options.objectName)) {
86+
options.fileSizeLimit = 0
87+
}
88+
8489
try {
8590
const file = await this.incomingFileInfo(request, options)
8691

87-
if (options.allowedMimeTypes) {
92+
if (options.allowedMimeTypes && !isEmptyFolder(options.objectName)) {
8893
this.validateMimeType(file.mimeType, options.allowedMimeTypes)
8994
}
9095

src/test/object.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,43 @@ describe('testing POST object via multipart upload', () => {
380380
expect(S3Backend.prototype.uploadObject).not.toHaveBeenCalled()
381381
})
382382

383+
test('can create an empty folder when mime-type is set', async () => {
384+
const form = new FormData()
385+
const headers = Object.assign({}, form.getHeaders(), {
386+
authorization: `Bearer ${serviceKey}`,
387+
'x-upsert': 'true',
388+
})
389+
390+
form.append('file', Buffer.alloc(0))
391+
392+
const response = await app().inject({
393+
method: 'POST',
394+
url: '/object/public-limit-mime-types/nested/.emptyFolderPlaceholder',
395+
headers,
396+
payload: form,
397+
})
398+
expect(response.statusCode).toBe(200)
399+
expect(S3Backend.prototype.uploadObject).toHaveBeenCalled()
400+
})
401+
402+
test('cannot create an empty folder with more than 0kb', async () => {
403+
const form = new FormData()
404+
const headers = Object.assign({}, form.getHeaders(), {
405+
authorization: `Bearer ${serviceKey}`,
406+
'x-upsert': 'true',
407+
})
408+
409+
form.append('file', Buffer.alloc(1))
410+
411+
const response = await app().inject({
412+
method: 'POST',
413+
url: '/object/public-limit-mime-types/nested-2/.emptyFolderPlaceholder',
414+
headers,
415+
payload: form,
416+
})
417+
expect(response.statusCode).toBe(400)
418+
})
419+
383420
test('return 422 when uploading an object with a malformed mime-type', async () => {
384421
const form = new FormData()
385422
form.append('file', fs.createReadStream(`./src/test/assets/sadcat.jpg`))

0 commit comments

Comments
 (0)