From a75ae38308f49f0d99a72d5eeda5b25cd7706657 Mon Sep 17 00:00:00 2001 From: EYHN Date: Wed, 30 Apr 2025 10:25:15 +0800 Subject: [PATCH] fix(nbstore): fix cloud blob in ios and android (#11938) --- .../server/src/core/workspaces/controller.ts | 7 +++- .../common/nbstore/src/impls/cloud/blob.ts | 34 +++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/backend/server/src/core/workspaces/controller.ts b/packages/backend/server/src/core/workspaces/controller.ts index ca314c0a2..de2522650 100644 --- a/packages/backend/server/src/core/workspaces/controller.ts +++ b/packages/backend/server/src/core/workspaces/controller.ts @@ -70,7 +70,12 @@ export class WorkspacesController { // metadata should always exists if body is not null if (metadata) { - res.setHeader('content-type', metadata.contentType); + res.setHeader( + 'content-type', + metadata.contentType.startsWith('application/json') // application/json is reserved for redirect url + ? 'text/json' + : metadata.contentType + ); res.setHeader('last-modified', metadata.lastModified.toUTCString()); res.setHeader('content-length', metadata.contentLength); } else { diff --git a/packages/common/nbstore/src/impls/cloud/blob.ts b/packages/common/nbstore/src/impls/cloud/blob.ts index 8a35edb2c..7c3711739 100644 --- a/packages/common/nbstore/src/impls/cloud/blob.ts +++ b/packages/common/nbstore/src/impls/cloud/blob.ts @@ -20,6 +20,8 @@ interface CloudBlobStorageOptions { id: string; } +const SHOULD_MANUAL_REDIRECT = BUILD_CONFIG.isAndroid || BUILD_CONFIG.isIOS; + export class CloudBlobStorage extends BlobStorageBase { static readonly identifier = 'CloudBlobStorage'; override readonly isReadonly = false; @@ -32,7 +34,11 @@ export class CloudBlobStorage extends BlobStorageBase { override async get(key: string, signal?: AbortSignal) { const res = await this.connection.fetch( - '/api/workspaces/' + this.options.id + '/blobs/' + key, + '/api/workspaces/' + + this.options.id + + '/blobs/' + + key + + (SHOULD_MANUAL_REDIRECT ? '?redirect=manual' : ''), { cache: 'default', headers: { @@ -47,7 +53,31 @@ export class CloudBlobStorage extends BlobStorageBase { } try { - const blob = await res.blob(); + const contentType = res.headers.get('content-type'); + + let blob; + + if ( + SHOULD_MANUAL_REDIRECT && + contentType?.startsWith('application/json') + ) { + const json = await res.json(); + if ('url' in json && typeof json.url === 'string') { + const res = await this.connection.fetch(json.url, { + cache: 'default', + headers: { + 'x-affine-version': BUILD_CONFIG.appVersion, + }, + signal, + }); + + blob = await res.blob(); + } else { + throw new Error('Invalid blob response'); + } + } else { + blob = await res.blob(); + } return { key,