From 54e3fccd8763c1138af71ad129ed138e06765d84 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 7 Jan 2023 14:19:25 +0900 Subject: [PATCH] enhance(server): refactor and tweak emoji proxy --- packages/backend/assets/emoji-unknown.png | Bin 0 -> 3518 bytes packages/backend/src/server/ServerService.ts | 43 +++++++++++++++++- .../src/server/web/ClientServerService.ts | 42 ----------------- 3 files changed, 41 insertions(+), 44 deletions(-) create mode 100644 packages/backend/assets/emoji-unknown.png diff --git a/packages/backend/assets/emoji-unknown.png b/packages/backend/assets/emoji-unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..ab29bef2b17ba5aaca78d8f809a010bc29970225 GIT binary patch literal 3518 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 fB~=PWz4VW%LrP-)!S_Y4LESD-S3j3^P6('/emoji/:path(.*)', async (request, reply) => { + const path = request.params.path; + + if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) { + reply.code(404); + return; + } + + reply.header('Cache-Control', 'public, max-age=86400'); + + const name = path.split('@')[0].replace('.webp', ''); + const host = path.split('@')[1]?.replace('.webp', ''); + + const emoji = await this.emojisRepository.findOneBy({ + // `@.` is the spec of ReactionService.decodeReaction + host: (host == null || host === '.') ? IsNull() : host, + name: name, + }); + + reply.header('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\''); + + if (emoji == null) { + return await reply.redirect('/static-assets/emoji-unknown.png'); + } + + const url = new URL('/proxy/emoji.webp', this.config.url); + // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ) + url.searchParams.set('url', emoji.publicUrl || emoji.originalUrl); + url.searchParams.set('emoji', '1'); + if ('static' in request.query) url.searchParams.set('static', '1'); + + return await reply.redirect( + 301, + url.toString(), + ); + }); + fastify.get<{ Params: { acct: string } }>('/avatar/@:acct', async (request, reply) => { const { username, host } = Acct.parse(request.params.acct); const user = await this.usersRepository.findOne({ diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index a7701e1b24..c69975fd79 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -1,6 +1,5 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; -import { PathOrFileDescriptor, readFileSync } from 'node:fs'; import { Inject, Injectable } from '@nestjs/common'; import { createBullBoard } from '@bull-board/api'; import { BullAdapter } from '@bull-board/api/bullAdapter.js'; @@ -71,9 +70,6 @@ export class ClientServerService { @Inject(DI.pagesRepository) private pagesRepository: PagesRepository, - @Inject(DI.emojisRepository) - private emojisRepository: EmojisRepository, - @Inject(DI.flashsRepository) private flashsRepository: FlashsRepository, @@ -225,44 +221,6 @@ export class ClientServerService { return reply.sendFile('/apple-touch-icon.png', staticAssets); }); - fastify.get<{ Params: { path: string }; Querystring: { static?: any; }; }>('/emoji/:path(.*)', async (request, reply) => { - const path = request.params.path; - - if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) { - reply.code(404); - return; - } - - reply.header('Cache-Control', 'public, max-age=86400'); - - const name = path.split('@')[0].replace('.webp', ''); - const host = path.split('@')[1]?.replace('.webp', ''); - - const emoji = await this.emojisRepository.findOneBy({ - // `@.` is the spec of ReactionService.decodeReaction - host: (host == null || host === '.') ? IsNull() : host, - name: name, - }); - - if (emoji == null) { - reply.code(404); - return; - } - - reply.header('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\''); - - const url = new URL('/proxy/emoji.webp', this.config.url); - // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ) - url.searchParams.set('url', emoji.publicUrl || emoji.originalUrl); - url.searchParams.set('emoji', '1'); - if ('static' in request.query) url.searchParams.set('static', '1'); - - return await reply.redirect( - 301, - url.toString(), - ); - }); - fastify.get<{ Params: { path: string } }>('/fluent-emoji/:path(.*)', async (request, reply) => { const path = request.params.path;