mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-01 05:54:12 +00:00 
			
		
		
		
	merge: Bump version (!762)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/762
This commit is contained in:
		
						commit
						2234fbcb11
					
				
					 2 changed files with 1 additions and 90 deletions
				
			
		|  | @ -1,6 +1,6 @@ | ||||||
| { | { | ||||||
| 	"name": "sharkey", | 	"name": "sharkey", | ||||||
| 	"version": "2024.9.2", | 	"version": "2024.9.3", | ||||||
| 	"codename": "shonk", | 	"codename": "shonk", | ||||||
| 	"repository": { | 	"repository": { | ||||||
| 		"type": "git", | 		"type": "git", | ||||||
|  |  | ||||||
|  | @ -28,11 +28,7 @@ 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 { handleRequestRedirectToOmitSearch } from '@/misc/fastify-hook-handlers.js'; | ||||||
| import { RateLimiterService } from '@/server/api/RateLimiterService.js'; |  | ||||||
| import { getIpHash } from '@/misc/get-ip-hash.js'; |  | ||||||
| import { AuthenticateService } from '@/server/api/AuthenticateService.js'; |  | ||||||
| import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify'; | import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify'; | ||||||
| import type Limiter from 'ratelimiter'; |  | ||||||
| 
 | 
 | ||||||
| const _filename = fileURLToPath(import.meta.url); | const _filename = fileURLToPath(import.meta.url); | ||||||
| const _dirname = dirname(_filename); | const _dirname = dirname(_filename); | ||||||
|  | @ -56,8 +52,6 @@ export class FileServerService { | ||||||
| 		private videoProcessingService: VideoProcessingService, | 		private videoProcessingService: VideoProcessingService, | ||||||
| 		private internalStorageService: InternalStorageService, | 		private internalStorageService: InternalStorageService, | ||||||
| 		private loggerService: LoggerService, | 		private loggerService: LoggerService, | ||||||
| 		private authenticateService: AuthenticateService, |  | ||||||
| 		private rateLimiterService: RateLimiterService, |  | ||||||
| 	) { | 	) { | ||||||
| 		this.logger = this.loggerService.getLogger('server', 'gray'); | 		this.logger = this.loggerService.getLogger('server', 'gray'); | ||||||
| 
 | 
 | ||||||
|  | @ -82,8 +76,6 @@ export class FileServerService { | ||||||
| 			}); | 			}); | ||||||
| 
 | 
 | ||||||
| 			fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => { | 			fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => { | ||||||
| 				if (!await this.checkRateLimit(request, reply, `/files/${request.params.key}`)) return; |  | ||||||
| 
 |  | ||||||
| 				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)); | ||||||
| 			}); | 			}); | ||||||
|  | @ -97,20 +89,6 @@ export class FileServerService { | ||||||
| 			Params: { url: string; }; | 			Params: { url: string; }; | ||||||
| 			Querystring: { url?: string; }; | 			Querystring: { url?: string; }; | ||||||
| 		}>('/proxy/:url*', async (request, reply) => { | 		}>('/proxy/:url*', async (request, reply) => { | ||||||
| 			const url = 'url' in request.query ? request.query.url : 'https://' + request.params.url; |  | ||||||
| 			if (!url || !URL.canParse(url)) { |  | ||||||
| 				reply.code(400); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			const keyUrl = new URL(url); |  | ||||||
| 			keyUrl.searchParams.forEach(k => keyUrl.searchParams.delete(k)); |  | ||||||
| 			keyUrl.hash = ''; |  | ||||||
| 			keyUrl.username = ''; |  | ||||||
| 			keyUrl.password = ''; |  | ||||||
| 
 |  | ||||||
| 			if (!await this.checkRateLimit(request, reply, `/proxy/${keyUrl}`)) return; |  | ||||||
| 
 |  | ||||||
| 			return await this.proxyHandler(request, reply) | 			return await this.proxyHandler(request, reply) | ||||||
| 				.catch(err => this.errorHandler(request, reply, err)); | 				.catch(err => this.errorHandler(request, reply, err)); | ||||||
| 		}); | 		}); | ||||||
|  | @ -594,71 +572,4 @@ export class FileServerService { | ||||||
| 			path, | 			path, | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	// Based on ApiCallService
 |  | ||||||
| 	private async checkRateLimit( |  | ||||||
| 		request: FastifyRequest<{ |  | ||||||
| 			Body?: Record<string, unknown> | undefined, |  | ||||||
| 			Querystring?: Record<string, unknown> | undefined, |  | ||||||
| 			Params?: Record<string, unknown> | unknown, |  | ||||||
| 		}>, |  | ||||||
| 		reply: FastifyReply, |  | ||||||
| 		rateLimitKey: string, |  | ||||||
| 	): Promise<boolean> { |  | ||||||
| 		const body = request.method === 'GET' |  | ||||||
| 			? request.query |  | ||||||
| 			: request.body; |  | ||||||
| 
 |  | ||||||
| 		// https://datatracker.ietf.org/doc/html/rfc6750.html#section-2.1 (case sensitive)
 |  | ||||||
| 		const token = request.headers.authorization?.startsWith('Bearer ') |  | ||||||
| 			? request.headers.authorization.slice(7) |  | ||||||
| 			: body?.['i']; |  | ||||||
| 		if (token != null && typeof token !== 'string') { |  | ||||||
| 			reply.code(400); |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// koa will automatically load the `X-Forwarded-For` header if `proxy: true` is configured in the app.
 |  | ||||||
| 		const [user] = await this.authenticateService.authenticate(token); |  | ||||||
| 		const actor = user?.id ?? getIpHash(request.ip); |  | ||||||
| 
 |  | ||||||
| 		const limit = { |  | ||||||
| 			// Group by resource
 |  | ||||||
| 			key: rateLimitKey, |  | ||||||
| 
 |  | ||||||
| 			// Maximum of 10 requests / 10 minutes
 |  | ||||||
| 			max: 10, |  | ||||||
| 			duration: 1000 * 60 * 10, |  | ||||||
| 
 |  | ||||||
| 			// Minimum of 250 ms between each request
 |  | ||||||
| 			minInterval: 250, |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		// Rate limit proxy requests
 |  | ||||||
| 		try { |  | ||||||
| 			await this.rateLimiterService.limit(limit, actor); |  | ||||||
| 			return true; |  | ||||||
| 		} catch (err) { |  | ||||||
| 			// errはLimiter.LimiterInfoであることが期待される
 |  | ||||||
| 			reply.code(429); |  | ||||||
| 
 |  | ||||||
| 			if (hasRateLimitInfo(err)) { |  | ||||||
| 				const cooldownInSeconds = Math.ceil((err.info.resetMs - Date.now()) / 1000); |  | ||||||
| 				// もしかするとマイナスになる可能性がなくはないのでマイナスだったら0にしておく
 |  | ||||||
| 				reply.header('Retry-After', Math.max(cooldownInSeconds, 0).toString(10)); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			reply.send({ |  | ||||||
| 				message: 'Rate limit exceeded. Please try again later.', |  | ||||||
| 				code: 'RATE_LIMIT_EXCEEDED', |  | ||||||
| 				id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef', |  | ||||||
| 			}); |  | ||||||
| 
 |  | ||||||
| 			return false; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function hasRateLimitInfo(err: unknown): err is { info: Limiter.LimiterInfo } { |  | ||||||
| 	return err != null && typeof(err) === 'object' && 'info' in err; |  | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue