perf: omit search for immutable static requests (#13265)

* perf: omit search for immutable static requests

* perf: also applies to /files

* fix: exclude /proxy

* /files/:key/*を301 redirectに

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
This commit is contained in:
Acid Chicken (硫酸鶏) 2024-02-13 01:43:06 +00:00 committed by GitHub
parent 50817df59c
commit 309a943528
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 23 deletions

View file

@ -0,0 +1,9 @@
import type { onRequestHookHandler } from 'fastify';
export const handleRequestRedirectToOmitSearch: onRequestHookHandler = (request, reply, done) => {
const index = request.url.indexOf('?');
if (~index) {
reply.redirect(301, request.url.slice(0, index));
}
done();
};

View file

@ -27,6 +27,7 @@ import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isMimeImage } from '@/misc/is-mime-image.js'; import { isMimeImage } from '@/misc/is-mime-image.js';
import { correctFilename } from '@/misc/correct-filename.js'; import { correctFilename } from '@/misc/correct-filename.js';
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify'; import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
const _filename = fileURLToPath(import.meta.url); const _filename = fileURLToPath(import.meta.url);
@ -67,20 +68,23 @@ export class FileServerService {
done(); done();
}); });
fastify.get('/files/app-default.jpg', (request, reply) => { fastify.register((fastify, options, done) => {
const file = fs.createReadStream(`${_dirname}/assets/dummy.png`); fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
reply.header('Content-Type', 'image/jpeg'); fastify.get('/files/app-default.jpg', (request, reply) => {
reply.header('Cache-Control', 'max-age=31536000, immutable'); const file = fs.createReadStream(`${_dirname}/assets/dummy.png`);
return reply.send(file); 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) => { fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => {
return await this.sendDriveFile(request, reply) return await this.sendDriveFile(request, reply)
.catch(err => this.errorHandler(request, reply, err)); .catch(err => this.errorHandler(request, reply, err));
}); });
fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => { fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => {
return await this.sendDriveFile(request, reply) return await reply.redirect(301, `${this.config.url}/files/${request.params.key}`);
.catch(err => this.errorHandler(request, reply, err)); });
done();
}); });
fastify.get<{ fastify.get<{

View file

@ -34,6 +34,7 @@ import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, MiMeta, NotesRepository, PagesRepository, ReversiGamesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { deepClone } from '@/misc/clone.js'; import { deepClone } from '@/misc/clone.js';
import { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { FlashEntityService } from '@/core/entities/FlashEntityService.js'; import { FlashEntityService } from '@/core/entities/FlashEntityService.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
@ -253,11 +254,16 @@ export class ClientServerService {
//#region vite assets //#region vite assets
if (this.config.clientManifestExists) { if (this.config.clientManifestExists) {
fastify.register(fastifyStatic, { fastify.register((fastify, options, done) => {
root: viteOut, fastify.register(fastifyStatic, {
prefix: '/vite/', root: viteOut,
maxAge: ms('30 days'), prefix: '/vite/',
decorateReply: false, maxAge: ms('30 days'),
immutable: true,
decorateReply: false,
});
fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
done();
}); });
} else { } else {
const port = (process.env.VITE_PORT ?? '5173'); const port = (process.env.VITE_PORT ?? '5173');
@ -292,11 +298,16 @@ export class ClientServerService {
decorateReply: false, decorateReply: false,
}); });
fastify.register(fastifyStatic, { fastify.register((fastify, options, done) => {
root: tarball, fastify.register(fastifyStatic, {
prefix: '/tarball/', root: tarball,
immutable: true, prefix: '/tarball/',
decorateReply: false, maxAge: ms('30 days'),
immutable: true,
decorateReply: false,
});
fastify.addHook('onRequest', handleRequestRedirectToOmitSearch);
done();
}); });
fastify.get('/favicon.ico', async (request, reply) => { fastify.get('/favicon.ico', async (request, reply) => {