fix(home-server): accept application/octet-stream requests for files (#625)

* fix(home-server): accept application/octet-stream requests for files

* fix(files): check for empty chunks
This commit is contained in:
Karol Sójko
2023-06-12 11:55:18 +02:00
committed by GitHub
parent 3654a19586
commit c8974b7fa2
4 changed files with 42 additions and 5 deletions
@@ -26,6 +26,24 @@ describe('UploadFileChunk', () => {
logger.warn = jest.fn()
})
it('should not upload a data chunk with 0 bytes', async () => {
expect(
await createUseCase().execute({
chunkId: 2,
data: new Uint8Array([]),
resourceRemoteIdentifier: '2-3-4',
resourceUnencryptedFileSize: 123,
userUuid: '1-2-3',
}),
).toEqual({
success: false,
message: 'Empty file chunk',
})
expect(fileUploader.uploadFileChunk).not.toHaveBeenCalled()
expect(uploadRepository.storeUploadChunkResult).not.toHaveBeenCalled()
})
it('should not upload a data chunk to a non existing file upload session', async () => {
uploadRepository.retrieveUploadSessionId = jest.fn().mockReturnValue(undefined)
@@ -18,6 +18,17 @@ export class UploadFileChunk implements UseCaseInterface {
async execute(dto: UploadFileChunkDTO): Promise<UploadFileChunkResponse> {
try {
if (!dto.data.byteLength || dto.data.byteLength === 0) {
this.logger.debug(
`Skipping upload file chunk ${dto.chunkId} with 0 bytes for resource: ${dto.resourceRemoteIdentifier}`,
)
return {
success: false,
message: 'Empty file chunk',
}
}
this.logger.debug(
`Starting upload file chunk ${dto.chunkId} with ${dto.data.byteLength} bytes for resource: ${dto.resourceRemoteIdentifier}`,
)
@@ -39,7 +39,9 @@ export class FSFileUploader implements FileUploaderInterface {
)
}
this.logger.debug(`FS storing file chunk ${dto.chunkId} in memory for ${dto.uploadId}`)
this.logger.debug(
`FS storing file chunk ${dto.chunkId} in memory for ${dto.uploadId}: ${dto.data}, ${dto.data.byteLength}`,
)
fileChunks.set(dto.chunkId, dto.data)
@@ -61,11 +63,12 @@ export class FSFileUploader implements FileUploaderInterface {
const orderedKeys = [...fileChunks.keys()].sort((a, b) => a - b)
for (const orderedKey of orderedKeys) {
const chunk = fileChunks.get(orderedKey)
if (!chunk) {
if (!chunk || chunk.byteLength === 0) {
throw new Error(`Could not find chunk ${orderedKey} for upload ${uploadId}`)
}
this.logger.debug(`FS writing chunk ${orderedKey} for ${uploadId}: ${JSON.stringify(chunk)}`)
this.logger.debug(`FS writing chunk ${orderedKey} for ${uploadId}: ${chunk.toString()} ${chunk.byteLength}}`)
await promises.appendFile(`${this.fileUploadPath}/${filePath}`, chunk)
}
@@ -12,7 +12,7 @@ import { InversifyExpressServer } from 'inversify-express-utils'
import helmet from 'helmet'
import * as cors from 'cors'
import * as http from 'http'
import { text, json, Request, Response, NextFunction } from 'express'
import { text, json, Request, Response, NextFunction, raw } from 'express'
import * as winston from 'winston'
import { PassThrough } from 'stream'
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -104,12 +104,17 @@ export class HomeServer implements HomeServerInterface {
}))
/* eslint-enable */
app.use(json({ limit: '50mb' }))
app.use(raw({ limit: '50mb', type: 'application/octet-stream' }))
app.use(
text({
type: ['text/plain', 'application/x-www-form-urlencoded', 'application/x-www-form-urlencoded; charset=utf-8'],
}),
)
app.use(cors())
app.use(
cors({
exposedHeaders: ['Content-Range', 'Accept-Ranges'],
}),
)
app.use(
robots({
UserAgent: '*',