diff --git a/package.json b/package.json index 426d774d..9ce9330f 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "formik": "^2.4.6", "gravatar-url": "3.1.0", "lodash": "4.17.21", + "mime": "3", "next": "^14.2.4", "node-cache": "5.1.2", "node-gyp": "9.3.1", @@ -119,6 +120,7 @@ "@types/express": "4.17.17", "@types/express-session": "1.17.6", "@types/lodash": "4.14.191", + "@types/mime": "3", "@types/node": "20.14.8", "@types/node-schedule": "2.1.0", "@types/nodemailer": "6.4.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ea593fea..7391a775 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: lodash: specifier: 4.17.21 version: 4.17.21 + mime: + specifier: '3' + version: 3.0.0 next: specifier: ^14.2.4 version: 14.2.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -264,6 +267,9 @@ importers: '@types/lodash': specifier: 4.14.191 version: 4.14.191 + '@types/mime': + specifier: '3' + version: 3.0.4 '@types/node': specifier: 20.14.8 version: 20.14.8 @@ -2848,6 +2854,9 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/mime@3.0.4': + resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} + '@types/minimatch@3.0.5': resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} @@ -10836,7 +10845,7 @@ snapshots: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.6.2 + semver: 7.3.8 tar: 6.2.1 transitivePeerDependencies: - encoding @@ -10911,13 +10920,13 @@ snapshots: '@npmcli/fs@1.1.1': dependencies: '@gar/promisify': 1.1.3 - semver: 7.6.2 + semver: 7.3.8 optional: true '@npmcli/fs@2.1.2': dependencies: '@gar/promisify': 1.1.3 - semver: 7.6.2 + semver: 7.3.8 '@npmcli/move-file@1.1.2': dependencies: @@ -12326,7 +12335,7 @@ snapshots: read-pkg: 5.2.0 registry-auth-token: 5.0.2 semantic-release: 19.0.5(encoding@0.1.13) - semver: 7.6.2 + semver: 7.3.8 tempy: 1.0.1 '@semantic-release/release-notes-generator@10.0.3(semantic-release@19.0.5(encoding@0.1.13))': @@ -12670,6 +12679,8 @@ snapshots: '@types/mime@1.3.5': {} + '@types/mime@3.0.4': {} + '@types/minimatch@3.0.5': {} '@types/minimist@1.2.5': {} @@ -12887,7 +12898,7 @@ snapshots: debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.6.2 + semver: 7.3.8 tsutils: 3.21.0(typescript@4.9.5) optionalDependencies: typescript: 4.9.5 @@ -17269,7 +17280,7 @@ snapshots: nopt: 5.0.0 npmlog: 6.0.2 rimraf: 3.0.2 - semver: 7.6.2 + semver: 7.3.8 tar: 6.2.1 which: 2.0.2 transitivePeerDependencies: @@ -17348,7 +17359,7 @@ snapshots: dependencies: hosted-git-info: 4.1.0 is-core-module: 2.14.0 - semver: 7.6.2 + semver: 7.3.8 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} diff --git a/server/lib/imageproxy.ts b/server/lib/imageproxy.ts index aae09314..3b61e842 100644 --- a/server/lib/imageproxy.ts +++ b/server/lib/imageproxy.ts @@ -3,6 +3,7 @@ import type { RateLimitOptions } from '@server/utils/rateLimit'; import rateLimit from '@server/utils/rateLimit'; import { createHash } from 'crypto'; import { promises } from 'fs'; +import mime from 'mime/lite'; import path, { join } from 'path'; type ImageResponse = { @@ -11,7 +12,7 @@ type ImageResponse = { curRevalidate: number; isStale: boolean; etag: string; - extension: string; + extension: string | null; cacheKey: string; cacheMiss: boolean; }; @@ -250,7 +251,7 @@ class ImageProxy { const arrayBuffer = await response.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); - const extension = this.getMimeExtension( + const extension = mime.getExtension( response.headers.get('content-type') ?? '' ); @@ -294,7 +295,7 @@ class ImageProxy { private async writeToCacheDir( dir: string, - extension: string, + extension: string | null, maxAge: number, expireAt: number, buffer: Buffer, @@ -329,31 +330,6 @@ class ImageProxy { private getCacheDirectory() { return path.join(baseCacheDirectory, this.key); } - - private getMimeExtension(mime: string): string { - switch (mime) { - case 'image/png': - return 'png'; - case 'image/jpeg': - return 'jpeg'; - case 'image/jpg': - return 'jpg'; - case 'image/apng': - return 'apng'; - case 'image/gif': - return 'gif'; - case 'image/vnd.microsoft.icon': - return 'ico'; - case 'image/tiff': - return 'tiff'; - case 'image/webp': - return 'webp'; - default: - break; - } - - return ''; - } } export default ImageProxy;