v1.9.0: Full diagnostic sweep - 42 issues fixed

Critical fixes (7):
- Added global Express error handler (returns JSON instead of HTML)
- Removed caching from random endpoint (defeated purpose)
- Renamed share.jpg to share.png (MIME type mismatch)
- Fixed OG image dimensions (630 → 601)
- Fixed manifest.json icon sizes (192x192 → 512x512)
- Fixed implicit global event variable in console
- Added 9 missing endpoints to docs/endpoints.md

High fixes (12):
- Imported version from package.json (no hardcoded drift)
- Added dynamic endpoint count in stats
- Added input sanitization for mapper API (SSRF prevention)
- Added homepage caching (reduced 5 duplicate HTTP requests)
- Added rate limiting (100 requests/minute per IP)
- Added rel="noopener noreferrer" to all target="_blank" links
- Fixed trailing slash inconsistency in console
- Added noindex meta to 404.html
- Fixed docs/architecture.md controller filenames and dependency versions
- Fixed README.md dependency versions
- Added 12 missing endpoint tests

Medium fixes (22):
- Added escapeHtml helper for error messages
- Consistent favicon across all pages
- Added meta descriptions to privacy.html and tos.html
- Added OG/Twitter meta tags to privacy.html and tos.html
- Added aria-label to playground inputs
- Added aria-hidden to decorative SVGs
- Synced Twitter description with OG description
- Fixed robots.txt to disallow /api
- Added PWA fields to manifest.json
- Removed 5 unused imports
- Removed unused cookie-parser dependency
- Fixed inconsistent error handling in extractors
- Fixed resolvedSlug returning numeric ID
- Added /watch endpoint to streaming docs
- Improved test assertions and status code validation
- Deleted orphaned og-image.svg and logo.png

Low fixes (11):
- Removed redundant try/catch from extractPages
- Added max size eviction to cache
- Added cache key sorting in filter controller
- Added author meta tag
- Fixed favicon.svg font

Version bumped to 1.9.0
This commit is contained in:
Sʜɪɴᴇɪ Nᴏᴜᴢᴇɴ
2026-06-09 06:00:37 +05:30
parent 84c4877669
commit 100b9f9414
30 changed files with 404 additions and 139 deletions
+27 -1
View File
@@ -36,6 +36,7 @@ const PORT = process.env.PORT || 4444;
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const publicDir = path.join(process.cwd(), "public");
const has404File = fs.existsSync(path.join(publicDir, "404.html"));
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",");
// ══════════════════════════════════════════════════════════════
@@ -45,7 +46,7 @@ const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",");
// NOTE: Single unified CORS middleware — handles all origin validation
app.use((req, res, next) => {
const origin = req.headers.origin;
if (!allowedOrigins || allowedOrigins.includes("*") || (origin && allowedOrigins.includes(origin))) {
if (allowedOrigins && (allowedOrigins.includes("*") || (origin && allowedOrigins.includes(origin)))) {
res.setHeader("Access-Control-Allow-Origin", origin || "*");
}
res.setHeader("Access-Control-Allow-Methods", "GET");
@@ -116,12 +117,37 @@ const jsonError = (res, message = "Internal server error", status = 500) =>
// API ROUTES
// ══════════════════════════════════════════════════════════════
// ---- 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 now = Date.now();
const windowMs = 60000;
const maxRequests = 100;
if (!requestCounts.has(ip)) {
requestCounts.set(ip, []);
}
const timestamps = requestCounts.get(ip).filter(t => now - t < windowMs);
requestCounts.set(ip, timestamps);
if (timestamps.length >= maxRequests) {
return res.status(429).json({ success: false, message: "Rate limit exceeded. Try again later." });
}
timestamps.push(now);
next();
});
createApiRoutes(app, jsonResponse, jsonError);
// ══════════════════════════════════════════════════════════════
// 404 HANDLER
// ══════════════════════════════════════════════════════════════
// ---- FEATURE: Global error handler ----
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({ success: false, message: err.message || "Internal server error" });
});
// ---- FEATURE: Catch-all 404 handler for undefined routes ----
app.use((req, res) => {
const filePath = path.join(publicDir, "404.html");