mirror of
https://github.com/Shineii86/MiruroAPI.git
synced 2026-10-22 10:15:10 +00:00
v1.4.0: Fix Vercel deployment, security headers, rate limiter, cache cleanup
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.0
|
||||
- Fixed Vercel deployment: replaced legacy `builds`/`routes` config with modern `functions` config
|
||||
- Added `api/index.js` serverless entry point (Vercel requires this for proper function detection)
|
||||
- Security headers: removed deprecated `X-XSS-Protection`, added `Strict-Transport-Security` (HSTS)
|
||||
- Rate limiter: uses `x-forwarded-for` header for correct IP detection on Vercel serverless
|
||||
- Rate limiter: added periodic IP entry pruning when >200 IPs tracked (prevents memory leak)
|
||||
- Cache: added periodic expired entry cleanup when cache reaches 80% capacity (prevents memory leak)
|
||||
- Version synced to 1.4.0 across all files (server.js, package.json, health endpoint, OpenAPI spec)
|
||||
|
||||
## v1.3.0
|
||||
- Full landing page upgrade to match AniKotoAPI style
|
||||
- Added canvas particle effects with cyan-colored floating particles
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require("../server");
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "miruro-api",
|
||||
"version": "1.3.0",
|
||||
"version": "1.4.0",
|
||||
"description": "RESTful API for miruro.tv - Anime streaming data powered by AniList GraphQL and Miruro streaming providers",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -58,7 +58,7 @@ app.use((req, res, next) => {
|
||||
app.use((req, res, next) => {
|
||||
res.setHeader("X-Frame-Options", "DENY");
|
||||
res.setHeader("X-Content-Type-Options", "nosniff");
|
||||
res.setHeader("X-XSS-Protection", "1; mode=block");
|
||||
res.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
|
||||
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
|
||||
res.setHeader("Permissions-Policy", "camera=(), microphone=(), geolocation=()");
|
||||
next();
|
||||
@@ -128,7 +128,10 @@ const jsonError = (res, message = "Internal server error", status = 500) =>
|
||||
// ---- FEATURE: Rate limiting (100 requests per minute per IP) ----
|
||||
const requestCounts = new Map();
|
||||
app.use((req, res, next) => {
|
||||
const ip = req.ip || req.connection.remoteAddress;
|
||||
const ip =
|
||||
req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ||
|
||||
req.ip ||
|
||||
req.connection.remoteAddress;
|
||||
const now = Date.now();
|
||||
const windowMs = 60000;
|
||||
const maxRequests = 100;
|
||||
@@ -148,6 +151,16 @@ app.use((req, res, next) => {
|
||||
}
|
||||
|
||||
timestamps.push(now);
|
||||
|
||||
// NOTE: Periodic cleanup — prune expired IP entries every 60s to prevent memory leak
|
||||
if (requestCounts.size > 200) {
|
||||
for (const [key, val] of requestCounts) {
|
||||
if (val.filter((t) => now - t < windowMs).length === 0) {
|
||||
requestCounts.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
@@ -104,6 +104,15 @@ const setCache = (key, data, ttl = DEFAULT_TTL) => {
|
||||
cache.delete(firstKey);
|
||||
}
|
||||
|
||||
// NOTE: Periodic cleanup — prune all expired entries when cache reaches 80% capacity
|
||||
// Prevents unbounded memory growth from stale entries that were never accessed
|
||||
if (cache.size >= MAX_CACHE_SIZE * 0.8) {
|
||||
const now = Date.now();
|
||||
for (const [k, v] of cache) {
|
||||
if (now > v.expiry) cache.delete(k);
|
||||
}
|
||||
}
|
||||
|
||||
cache.set(key, { data, expiry: Date.now() + ttl });
|
||||
};
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ const createApiRoutes = (jsonResponse, jsonError) => {
|
||||
success: true,
|
||||
results: {
|
||||
status: "healthy",
|
||||
version: "1.2.0",
|
||||
version: "1.4.0",
|
||||
uptime: `${hours}h ${minutes}m ${seconds}s`,
|
||||
uptimeSeconds: uptime,
|
||||
timestamp: new Date().toISOString(),
|
||||
@@ -404,7 +404,7 @@ const createApiRoutes = (jsonResponse, jsonError) => {
|
||||
info: {
|
||||
title: "MiruroAPI",
|
||||
description: "Free REST API for anime streaming data — AniList GraphQL + Miruro streaming providers",
|
||||
version: "1.2.0",
|
||||
version: "1.4.0",
|
||||
contact: { name: "Shineii86", url: "https://github.com/Shineii86/MiruroAPI" },
|
||||
},
|
||||
servers: [
|
||||
|
||||
+5
-10
@@ -1,13 +1,8 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "server.js",
|
||||
"use": "@vercel/node"
|
||||
"functions": {
|
||||
"api/index.js": {
|
||||
"includeFiles": "src/**",
|
||||
"maxDuration": 30
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{ "src": "/api/(.*)", "dest": "server.js" },
|
||||
{ "src": "/(.*)", "dest": "server.js" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user