diff options
| author | Fuwn <[email protected]> | 2023-12-24 00:59:14 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-12-24 00:59:14 -0800 |
| commit | 31ea88d915e27d15efd7c110f8189130338c759b (patch) | |
| tree | df6fce79682d33890505857084adf52d13d60063 | |
| parent | fix(subtiteld): lessen subtitled match (diff) | |
| download | due.moe-31ea88d915e27d15efd7c110f8189130338c759b.tar.xz due.moe-31ea88d915e27d15efd7c110f8189130338c759b.zip | |
feat(mangadex): server-side rate-limit 5/s
| -rwxr-xr-x | bun.lockb | bin | 125230 -> 126026 bytes | |||
| -rw-r--r-- | package.json | 93 | ||||
| -rw-r--r-- | src/lib/rateLimit.ts | 12 | ||||
| -rw-r--r-- | src/routes/api/mangadex/chapter/+server.ts | 9 | ||||
| -rw-r--r-- | src/routes/api/mangadex/feed/+server.ts | 10 | ||||
| -rw-r--r-- | src/routes/api/mangadex/manga/+server.ts | 9 |
6 files changed, 83 insertions, 50 deletions
| Binary files differ diff --git a/package.json b/package.json index 0c09dadf..d47ed879 100644 --- a/package.json +++ b/package.json @@ -1,48 +1,49 @@ { - "name": "due.moe", - "version": "0.0.0", - "private": true, - "scripts": { - "dev": "vite dev", - "build": "vite build", - "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "lint": "prettier --plugin-search-dir . --check . && eslint .", - "format": "prettier --plugin-search-dir . --write ." - }, - "devDependencies": { - "@sveltejs/adapter-auto": "^2.0.0", - "@sveltejs/kit": "^1.20.4", - "@types/dom-to-image": "^2.6.5", - "@types/fast-levenshtein": "^0.0.4", - "@types/file-saver": "^2.0.5", - "@types/jsdom": "^21.1.6", - "@typescript-eslint/eslint-plugin": "^5.45.0", - "@typescript-eslint/parser": "^5.45.0", - "eslint": "^8.28.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-svelte": "^2.30.0", - "prettier": "^2.8.0", - "prettier-plugin-svelte": "^2.10.1", - "svelte": "^4.0.5", - "svelte-adapter-bun": "^0.5.0", - "svelte-check": "^3.4.3", - "tslib": "^2.4.1", - "typescript": "^5.0.0", - "vite": "^4.4.2" - }, - "type": "module", - "dependencies": { - "bun-types": "^1.0.15", - "dexie": "^4.0.1-alpha.25", - "fast-levenshtein": "^3.0.0", - "html2canvas": "^1.4.1", - "jsdom": "^23.0.1", - "modern-screenshot": "^4.4.33", - "rss-parser": "^3.13.0", - "socket.io": "^4.7.2", - "socket.io-client": "^4.7.2", - "wanakana": "^5.3.1" - } + "name": "due.moe", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --plugin-search-dir . --check . && eslint .", + "format": "prettier --plugin-search-dir . --write ." + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^2.0.0", + "@sveltejs/kit": "^1.20.4", + "@types/dom-to-image": "^2.6.5", + "@types/fast-levenshtein": "^0.0.4", + "@types/file-saver": "^2.0.5", + "@types/jsdom": "^21.1.6", + "@typescript-eslint/eslint-plugin": "^5.45.0", + "@typescript-eslint/parser": "^5.45.0", + "eslint": "^8.28.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-svelte": "^2.30.0", + "prettier": "^2.8.0", + "prettier-plugin-svelte": "^2.10.1", + "svelte": "^4.0.5", + "svelte-adapter-bun": "^0.5.0", + "svelte-check": "^3.4.3", + "sveltekit-rate-limiter": "^0.4.2", + "tslib": "^2.4.1", + "typescript": "^5.0.0", + "vite": "^4.4.2" + }, + "type": "module", + "dependencies": { + "bun-types": "^1.0.15", + "dexie": "^4.0.1-alpha.25", + "fast-levenshtein": "^3.0.0", + "html2canvas": "^1.4.1", + "jsdom": "^23.0.1", + "modern-screenshot": "^4.4.33", + "rss-parser": "^3.13.0", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", + "wanakana": "^5.3.1" + } } diff --git a/src/lib/rateLimit.ts b/src/lib/rateLimit.ts new file mode 100644 index 00000000..98e726a2 --- /dev/null +++ b/src/lib/rateLimit.ts @@ -0,0 +1,12 @@ +import type { RequestEvent } from '@sveltejs/kit'; +import { RateLimiter } from 'sveltekit-rate-limiter/server'; + +export const checkRateLimit = async (event: RequestEvent) => { + const limiter = new RateLimiter({ rates: { IP: [5, 's'] } }); + + await limiter.cookieLimiter?.preflight(event); + + if (await limiter.isLimited(event)) return new Response('rate-limited'); + + return null; +}; diff --git a/src/routes/api/mangadex/chapter/+server.ts b/src/routes/api/mangadex/chapter/+server.ts index 68e125bd..ad291e42 100644 --- a/src/routes/api/mangadex/chapter/+server.ts +++ b/src/routes/api/mangadex/chapter/+server.ts @@ -1,4 +1,11 @@ -export const GET = async ({ url }) => { +import { checkRateLimit } from '$lib/rateLimit.js'; + +export const GET = async (event) => { + const limit = await checkRateLimit(event); + const { url } = event; + + if (limit) return limit; + try { return Response.json( await ( diff --git a/src/routes/api/mangadex/feed/+server.ts b/src/routes/api/mangadex/feed/+server.ts index ebfdd094..458d3914 100644 --- a/src/routes/api/mangadex/feed/+server.ts +++ b/src/routes/api/mangadex/feed/+server.ts @@ -1,9 +1,15 @@ -export const GET = async ({ url }) => { +import { checkRateLimit } from '$lib/rateLimit.js'; + +export const GET = async (event) => { + const limit = await checkRateLimit(event); + + if (limit) return limit; + try { return Response.json( await ( await fetch( - `https://api.mangadex.org/manga/${url.searchParams.get( + `https://api.mangadex.org/manga/${event.url.searchParams.get( 'id' )}/feed?order[chapter]=desc&translatedLanguage[]=en&limit=1&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic` ) diff --git a/src/routes/api/mangadex/manga/+server.ts b/src/routes/api/mangadex/manga/+server.ts index 521bde6c..73c15481 100644 --- a/src/routes/api/mangadex/manga/+server.ts +++ b/src/routes/api/mangadex/manga/+server.ts @@ -1,4 +1,11 @@ -export const GET = async ({ url }) => { +import { checkRateLimit } from '$lib/rateLimit.js'; + +export const GET = async (event) => { + const limit = await checkRateLimit(event); + const { url } = event; + + if (limit) return limit; + let status = ''; let error = false; |