refactor(server): immich file responses (#5641)

* refactor(server): immich file response

* chore: open api

* chore: tests

* chore: fix logger import

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jason Rasmussen
2023-12-12 09:58:25 -05:00
committed by GitHub
parent af7c4ae090
commit cbca69841a
25 changed files with 186 additions and 154 deletions
@@ -0,0 +1,55 @@
import { ImmichFileResponse, isConnectionAborted } from '@app/domain';
import { CallHandler, ExecutionContext, Logger, NestInterceptor } from '@nestjs/common';
import { Response } from 'express';
import { access, constants } from 'fs/promises';
import { isAbsolute } from 'path';
import { Observable, mergeMap } from 'rxjs';
import { promisify } from 'util';
type SendFile = Parameters<Response['sendFile']>;
type SendFileOptions = SendFile[1];
export class FileServeInterceptor implements NestInterceptor {
private logger = new Logger(FileServeInterceptor.name);
intercept(context: ExecutionContext, next: CallHandler<any>): Observable<any> {
const http = context.switchToHttp();
const res = http.getResponse<Response>();
const sendFile = (path: string, options: SendFileOptions) =>
promisify<string, SendFileOptions>(res.sendFile).bind(res)(path, options);
return next.handle().pipe(
mergeMap(async (file) => {
if (file instanceof ImmichFileResponse === false) {
return file;
}
try {
if (file.cacheControl) {
res.set('Cache-Control', 'private, max-age=86400, no-transform');
}
res.header('Content-Type', file.contentType);
const options: SendFileOptions = { dotfiles: 'allow' };
if (!isAbsolute(file.path)) {
options.root = process.cwd();
}
await access(file.path, constants.R_OK);
return sendFile(file.path, options);
} catch (error: Error | any) {
res.header('Cache-Control', 'none');
if (!isConnectionAborted(error)) {
this.logger.error(`Unable to send file: ${error.name}`, error.stack);
}
// throwing closes the connection and prevents `Error: write EPIPE`
throw error;
}
}),
);
}
}
+2 -1
View File
@@ -1,2 +1,3 @@
export * from './error.interceptor';
export * from './file.interceptor';
export * from './file-serve.interceptor';
export * from './file-upload.interceptor';