Przeglądaj źródła

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
Karol Sójko 2 lat temu
rodzic
commit
c8974b7fa2

+ 18 - 0
packages/files/src/Domain/UseCase/UploadFileChunk/UploadFileChunk.spec.ts

@@ -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)
 

+ 11 - 0
packages/files/src/Domain/UseCase/UploadFileChunk/UploadFileChunk.ts

@@ -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}`,
       )

+ 6 - 3
packages/files/src/Infra/FS/FSFileUploader.ts

@@ -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)
     }
 

+ 7 - 2
packages/home-server/src/Server/HomeServer.ts

@@ -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: '*',