mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-07-25 20:14:55 +02:00
* enhance(backend): bundle backend using rolldown
* fix
* fix [ci skip]
* remove unused build script
* fix
* enhance: 起動からlistenまでかかる時間を減らす (MisskeyIO#1410)
* ✌️
* fix
* update rolldown
* fix(backend): extract static error classes to avoid rolldown design:paramtypes omission
* update rolldown
* Revert "fix(backend): extract static error classes to avoid rolldown design:paramtypes omission"
This reverts commit e2243c9dc3.
* fix
* perf: avoid generating sourcemap in production
* fix
* fix
* fix
* fix paths
* fix
* fix
* fix
* fix
* fix
* enhance: バックエンドの開発サーバー制御をrolldown側で行うように
* remove nodemon
* Update Changelog
* tweak config
* fix
* fix
* fix
* clean up
---------
Co-authored-by: あわわわとーにゅ <17376330+u1-liquid@users.noreply.github.com>
Co-authored-by: bab <mashirohira@gmail.com>
133 lines
4.6 KiB
TypeScript
133 lines
4.6 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
import * as fs from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import { Inject, Injectable } from '@nestjs/common';
|
|
import type { Config } from '@/config.js';
|
|
import type { DriveFilesRepository } from '@/models/_.js';
|
|
import { DI } from '@/di-symbols.js';
|
|
import { StatusError } from '@/misc/status-error.js';
|
|
import type Logger from '@/logger.js';
|
|
import { DownloadService } from '@/core/DownloadService.js';
|
|
import { InternalStorageService } from '@/core/InternalStorageService.js';
|
|
import { FileInfoService } from '@/core/FileInfoService.js';
|
|
import { ImageProcessingService } from '@/core/ImageProcessingService.js';
|
|
import { VideoProcessingService } from '@/core/VideoProcessingService.js';
|
|
import { LoggerService } from '@/core/LoggerService.js';
|
|
import { bindThis } from '@/decorators.js';
|
|
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
|
|
import { FileServerDriveHandler } from './file/FileServerDriveHandler.js';
|
|
import { FileServerFileResolver } from './file/FileServerFileResolver.js';
|
|
import { FileServerProxyHandler } from './file/FileServerProxyHandler.js';
|
|
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
|
|
|
|
@Injectable()
|
|
export class FileServerService {
|
|
private logger: Logger;
|
|
private driveHandler: FileServerDriveHandler;
|
|
private proxyHandler: FileServerProxyHandler;
|
|
private fileResolver: FileServerFileResolver;
|
|
|
|
private readonly assets: string;
|
|
|
|
constructor(
|
|
@Inject(DI.config)
|
|
private config: Config,
|
|
|
|
@Inject(DI.driveFilesRepository)
|
|
private driveFilesRepository: DriveFilesRepository,
|
|
|
|
private fileInfoService: FileInfoService,
|
|
private downloadService: DownloadService,
|
|
private imageProcessingService: ImageProcessingService,
|
|
private videoProcessingService: VideoProcessingService,
|
|
private internalStorageService: InternalStorageService,
|
|
private loggerService: LoggerService,
|
|
) {
|
|
this.logger = this.loggerService.getLogger('server', 'gray');
|
|
this.assets = resolve(this.config.rootDir, 'packages/backend/src/server/file/assets');
|
|
this.fileResolver = new FileServerFileResolver(
|
|
this.driveFilesRepository,
|
|
this.fileInfoService,
|
|
this.downloadService,
|
|
this.internalStorageService,
|
|
);
|
|
this.driveHandler = new FileServerDriveHandler(
|
|
this.config,
|
|
this.fileResolver,
|
|
this.assets,
|
|
this.videoProcessingService,
|
|
);
|
|
this.proxyHandler = new FileServerProxyHandler(
|
|
this.config,
|
|
this.fileResolver,
|
|
this.assets,
|
|
this.imageProcessingService,
|
|
);
|
|
|
|
//this.createServer = this.createServer.bind(this);
|
|
}
|
|
|
|
@bindThis
|
|
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
|
|
fastify.addHook('onRequest', (request, reply, done) => {
|
|
reply.header('Content-Security-Policy', 'default-src \'none\'; img-src \'self\'; media-src \'self\'; style-src \'unsafe-inline\'');
|
|
if (process.env.NODE_ENV === 'development') {
|
|
reply.header('Access-Control-Allow-Origin', '*');
|
|
}
|
|
done();
|
|
});
|
|
|
|
fastify.register((fastify, options, done) => {
|
|
fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
|
|
fastify.get('/files/app-default.jpg', (request, reply) => {
|
|
const file = fs.createReadStream(`${this.assets}/dummy.png`);
|
|
reply.header('Content-Type', 'image/jpeg');
|
|
reply.header('Cache-Control', 'max-age=31536000, immutable');
|
|
return reply.send(file);
|
|
});
|
|
|
|
fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => {
|
|
return await this.driveHandler.handle(request, reply)
|
|
.catch(err => this.errorHandler(request, reply, err));
|
|
});
|
|
fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => {
|
|
return await reply.redirect(`${this.config.url}/files/${request.params.key}`, 301);
|
|
});
|
|
done();
|
|
});
|
|
|
|
fastify.get<{
|
|
Params: { url: string; };
|
|
Querystring: { url?: string; };
|
|
}>('/proxy/:url*', async (request, reply) => {
|
|
return await this.proxyHandler.handle(request, reply)
|
|
.catch(err => this.errorHandler(request, reply, err));
|
|
});
|
|
|
|
done();
|
|
}
|
|
|
|
@bindThis
|
|
private async errorHandler(request: FastifyRequest<{ Params?: { [x: string]: any }; Querystring?: { [x: string]: any }; }>, reply: FastifyReply, err?: any) {
|
|
this.logger.error(`${err}`);
|
|
|
|
reply.header('Cache-Control', 'max-age=300');
|
|
|
|
if (request.query && 'fallback' in request.query) {
|
|
return reply.sendFile('/dummy.png', this.assets);
|
|
}
|
|
|
|
if (err instanceof StatusError && (err.statusCode === 302 || err.isClientError)) {
|
|
reply.code(err.statusCode);
|
|
return;
|
|
}
|
|
|
|
reply.code(500);
|
|
return;
|
|
}
|
|
}
|