From 812cb3d940d632c3f0e72be50a59b608abf3293a Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 6 Jul 2023 17:25:56 -0500 Subject: [PATCH] Revert "fix(server): use thumbnail content type instead of application/octet-stream (#3075)" (#3134) * Revert "fix(server): use thumbnail content type instead of application/octet-stream (#3075)" This reverts commit 3cc77d945b476db5e8bc24c8235bb99b7ef34186. * generate api --- cli/src/api/open-api/api.ts | 12 ++++----- mobile/openapi/doc/AssetApi.md | Bin 55965 -> 56109 bytes mobile/openapi/doc/PersonApi.md | Bin 10224 -> 10296 bytes mobile/openapi/lib/api/asset_api.dart | Bin 50143 -> 51103 bytes mobile/openapi/lib/api/person_api.dart | Bin 7882 -> 8362 bytes mobile/openapi/test/asset_api_test.dart | Bin 5312 -> 5342 bytes mobile/openapi/test/person_api_test.dart | Bin 1113 -> 1128 bytes server/immich-openapi-specs.json | 24 ++++++++++++++++++ .../immich/api-v1/asset/asset.controller.ts | 4 ++- .../src/immich/api-v1/asset/asset.service.ts | 13 +++++----- .../asset/dto/get-asset-thumbnail.dto.ts | 3 +-- .../immich/controllers/person.controller.ts | 3 ++- web/src/api/open-api/api.ts | 12 ++++----- 13 files changed, 48 insertions(+), 23 deletions(-) diff --git a/cli/src/api/open-api/api.ts b/cli/src/api/open-api/api.ts index 737d72da35..277d676daa 100644 --- a/cli/src/api/open-api/api.ts +++ b/cli/src/api/open-api/api.ts @@ -5895,7 +5895,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetThumbnail(id, format, key, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -5992,7 +5992,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.serveFile(id, isThumb, isWeb, key, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6161,7 +6161,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAssetThumbnail(requestParameters: AssetApiGetAssetThumbnailRequest, options?: AxiosRequestConfig): AxiosPromise { + getAssetThumbnail(requestParameters: AssetApiGetAssetThumbnailRequest, options?: AxiosRequestConfig): AxiosPromise { return localVarFp.getAssetThumbnail(requestParameters.id, requestParameters.format, requestParameters.key, options).then((request) => request(axios, basePath)); }, /** @@ -6240,7 +6240,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - serveFile(requestParameters: AssetApiServeFileRequest, options?: AxiosRequestConfig): AxiosPromise { + serveFile(requestParameters: AssetApiServeFileRequest, options?: AxiosRequestConfig): AxiosPromise { return localVarFp.serveFile(requestParameters.id, requestParameters.isThumb, requestParameters.isWeb, requestParameters.key, options).then((request) => request(axios, basePath)); }, /** @@ -8868,7 +8868,7 @@ export const PersonApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getPersonThumbnail(id: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getPersonThumbnail(id: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getPersonThumbnail(id, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -8925,7 +8925,7 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getPersonThumbnail(requestParameters: PersonApiGetPersonThumbnailRequest, options?: AxiosRequestConfig): AxiosPromise { + getPersonThumbnail(requestParameters: PersonApiGetPersonThumbnailRequest, options?: AxiosRequestConfig): AxiosPromise { return localVarFp.getPersonThumbnail(requestParameters.id, options).then((request) => request(axios, basePath)); }, /** diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md index 41f4e2e020ef5f96d3debff86a6fb542709834e6..319deb2acfff3bd01f7dbd55b5aedbc24d53a552 100644 GIT binary patch delta 99 zcmbQcm3i$p<_&9$C$nkuP425u+I+rv6U*d%>M}r%%H$n^p_{){h%rufGdwYQLy`Jq n0jtxS*HpJTfRt}G+Vd8oROcW_sqf~lgWAYSPizi3;wc6Ik7O%e delta 155 zcmZ3xjd|`?<_&9$H}5XK!ZLYYh2i8a8?7euM{#UcsT5WIRY=NDshq5sy`S4JzeFJ=H7zqQHD&U{&3iU~tnPG}Jn^8?=2d%6vrKL|2sUgp O(;;nA4SI6KQw#uELPJ3S diff --git a/mobile/openapi/doc/PersonApi.md b/mobile/openapi/doc/PersonApi.md index ca35880ddc6da3ae2fe5b9617779189dfd96c9bb..dd1c0eb8e41bfe56159ddd2de18e166253d5cd69 100644 GIT binary patch delta 115 zcmez1zawBns|25KX--LIL1IyfTV_tG!el;KvCXq3(pVb1F3UezoG*NGmh5)L zXe})irCM6C8Ylvj6V;Yaz9%O=xtD{7CqKC)wM4hLq$o8pck*10J(~~68*l&sm2xV6 delta 75 zcmV-R0JQ(OQ1DN%g&4Dw7<>ei9vvl=-8>%GH~^HiK*PzjQBqh;Z0)N5;*$tBhm;@=FvI diff --git a/mobile/openapi/lib/api/person_api.dart b/mobile/openapi/lib/api/person_api.dart index a27c5845f3e28d1f839d9377589208d6a23d4981..37f8bf8a307358c579014b775e6557a0c73d3db6 100644 GIT binary patch delta 74 zcmX?QyUKCHT`@l2(wvgag2bW{x6GVW`^gW*er=BBp310*BCf8ZsgPK#fFd?on%8>s IH}NZM0BPtQ9{>OV delta 21 dcmZ4Gc*=IeT``uj{LGZeuf=|C-Yxl_4FGVJ3RVCB diff --git a/mobile/openapi/test/asset_api_test.dart b/mobile/openapi/test/asset_api_test.dart index 003956969ccd335a2c07d0070e2abd992092837b..1c5f08536b4b523d28b34b11a12e67b1b7b12036 100644 GIT binary patch delta 25 ecmX@0c~5i0MefN{SOqp;;{MJGW}FiI#smPC1q%lN delta 17 Zcmcboc|dc+MefZHxPP#2elGZ(2>?-S2)qCQ diff --git a/mobile/openapi/test/person_api_test.dart b/mobile/openapi/test/person_api_test.dart index 956ec138d37377a5d014c9dcb824835bc50037bc..33e78b8a7cfc492f07c51984ff0c4030e4905457 100644 GIT binary patch delta 28 jcmcb~@q%N6J2StHZ)r|RW, @@ -135,6 +136,7 @@ export class AssetController { @SharedLinkRoute() @Get('/thumbnail/:id') @Header('Cache-Control', 'private, max-age=86400, no-transform') + @ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } }) getAssetThumbnail( @AuthUser() authUser: AuthUserDto, @Headers() headers: Record, diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 26c0ca7bbe..0a1ee8e0e2 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -256,8 +256,8 @@ export class AssetService { } try { - const [thumbnailPath, contentType] = this.getThumbnailPath(asset, query.format); - return this.streamFile(thumbnailPath, res, headers, contentType); + const thumbnailPath = this.getThumbnailPath(asset, query.format); + return this.streamFile(thumbnailPath, res, headers); } catch (e) { res.header('Cache-Control', 'none'); this.logger.error(`Cannot create read stream for asset ${asset.id}`, 'getAssetThumbnail'); @@ -522,17 +522,16 @@ export class AssetService { private getThumbnailPath(asset: AssetEntity, format: GetAssetThumbnailFormatEnum) { switch (format) { case GetAssetThumbnailFormatEnum.WEBP: - if (asset.webpPath) { - return [asset.webpPath, 'image/webp']; + if (asset.webpPath && asset.webpPath.length > 0) { + return asset.webpPath; } - this.logger.warn(`WebP thumbnail requested but not found for asset ${asset.id}, falling back to JPEG`); case GetAssetThumbnailFormatEnum.JPEG: default: if (!asset.resizePath) { - throw new NotFoundException(`No thumbnail found for asset ${asset.id}`); + throw new NotFoundException('resizePath not set'); } - return [asset.resizePath, 'image/jpeg']; + return asset.resizePath; } } diff --git a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts index ad0e755d6a..5a8dc06872 100644 --- a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts +++ b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsOptional } from 'class-validator'; +import { IsOptional } from 'class-validator'; export enum GetAssetThumbnailFormatEnum { JPEG = 'JPEG', @@ -8,7 +8,6 @@ export enum GetAssetThumbnailFormatEnum { export class GetAssetThumbnailDto { @IsOptional() - @IsEnum(GetAssetThumbnailFormatEnum) @ApiProperty({ type: String, enum: GetAssetThumbnailFormatEnum, diff --git a/server/src/immich/controllers/person.controller.ts b/server/src/immich/controllers/person.controller.ts index 2e8135161f..5752304598 100644 --- a/server/src/immich/controllers/person.controller.ts +++ b/server/src/immich/controllers/person.controller.ts @@ -7,7 +7,7 @@ import { PersonUpdateDto, } from '@app/domain'; import { Body, Controller, Get, Param, Put, StreamableFile } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; +import { ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { Authenticated, AuthUser } from '../app.guard'; import { UseValidation } from '../app.utils'; import { UUIDParamDto } from './dto/uuid-param.dto'; @@ -43,6 +43,7 @@ export class PersonController { } @Get(':id/thumbnail') + @ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } }) getPersonThumbnail(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto) { return this.service.getThumbnail(authUser, id).then(asStreamableFile); } diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 72b41daa7f..c1a8f7f222 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -5904,7 +5904,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetThumbnail(id, format, key, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6001,7 +6001,7 @@ export const AssetApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.serveFile(id, isThumb, isWeb, key, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -6181,7 +6181,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: any): AxiosPromise { + getAssetThumbnail(id: string, format?: ThumbnailFormat, key?: string, options?: any): AxiosPromise { return localVarFp.getAssetThumbnail(id, format, key, options).then((request) => request(axios, basePath)); }, /** @@ -6269,7 +6269,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath * @param {*} [options] Override http request option. * @throws {RequiredError} */ - serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: any): AxiosPromise { + serveFile(id: string, isThumb?: boolean, isWeb?: boolean, key?: string, options?: any): AxiosPromise { return localVarFp.serveFile(id, isThumb, isWeb, key, options).then((request) => request(axios, basePath)); }, /** @@ -8913,7 +8913,7 @@ export const PersonApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getPersonThumbnail(id: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + async getPersonThumbnail(id: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getPersonThumbnail(id, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -8970,7 +8970,7 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getPersonThumbnail(id: string, options?: any): AxiosPromise { + getPersonThumbnail(id: string, options?: any): AxiosPromise { return localVarFp.getPersonThumbnail(id, options).then((request) => request(axios, basePath)); }, /**