fix(v2.2.0): migrate to new Miruro pipe protocol — restore streaming endpoints

The streaming endpoints (/episodes, /sources, /stream, /watch, /download)
returned 500 because the upstream Miruro pipe changed and www.miruro.tv is
now hard-blocked by Cloudflare.

Reverse-engineered the current Miruro frontend contract:
- Request is plain base64url of the JSON payload (no XOR).
- Response obfuscation is now signalled by the x-obfuscated header:
  absent = plain JSON, 1 = base64+gzip, 2 = base64+XOR(PIPE_OBF_KEY)+gzip.

pipe.js now:
- rotates across mirrors (miruro.ru > .to > .bz > .tv), one per retry;
- decodes based on the x-obfuscated header instead of always XOR+gunzip;
- sends full browser sec-fetch/sec-ch-ua headers to pass Cloudflare checks;
- raises maxRetries to 4 and rotates on 403/444.

proxy.js default referer/Origin -> https://www.miruro.to (miruro.tv is dead).

AniList-backed endpoints were already healthy and are unaffected.
Version bumped to 2.2.0 across package.json, server.js, /api/health,
/api/openapi, public/openapi.json. CHANGELOG updated.
This commit is contained in:
Shinei Nouzen
2026-07-02 06:57:58 +05:30
parent 5a8879f2ba
commit 92154d7ea2
7 changed files with 138 additions and 39 deletions
+2 -2
View File
@@ -1123,7 +1123,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => {
success: true,
results: {
status: "healthy",
version: "2.1.4",
version: "2.2.0",
uptime: `${hours}h ${minutes}m ${seconds}s`,
uptimeSeconds: uptime,
timestamp: new Date().toISOString(),
@@ -1178,7 +1178,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => {
info: {
title: "MiruroAPI",
description: "Free REST API for anime streaming data — AniList GraphQL + Miruro streaming providers",
version: "2.1.4",
version: "2.2.0",
contact: { name: "Shineii86", url: "https://github.com/Shineii86/MiruroAPI" },
},
servers: [