mirror of
https://github.com/Shineii86/MiruroAPI.git
synced 2026-10-22 18:25:11 +00:00
- README.md: Added Worker deployment section, updated troubleshooting - Fix 1: Cloudflare Worker (best — free, works) - Fix 2: ScraperAPI (paid, 9/mo) - Fix 3: FlareSolverr (self-hosted) - Fix 4: Self-host API - Added Worker vs Vercel comparison table - docs/architecture.md: Added Worker architecture section - Why Workers work (edge-to-edge bypass) - Worker runtime differences table - 15 Worker endpoints listed - Deploy instructions - CHANGELOG.md: Added v2.3.1 entry for Worker edition
251 lines
8.2 KiB
Markdown
251 lines
8.2 KiB
Markdown
# Architecture
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
MiruroAPI/
|
|
├── server.js # Express entry point, port 3000
|
|
├── worker.js # Cloudflare Worker edition (edge runtime)
|
|
├── package.json # name: "miruro-api"
|
|
├── vercel.json # Routes /api/* and /* to server.js
|
|
├── Dockerfile # Docker support (node:20-alpine)
|
|
├── .dockerignore # Docker ignore file
|
|
│
|
|
├── public/ # Static files served from process.cwd()
|
|
│ ├── index.html # Premium landing page (SVG icons, live console)
|
|
│ ├── docs.html # Swagger UI interactive documentation
|
|
│ ├── openapi.json # OpenAPI 3.0 spec
|
|
│ ├── 404.html # Glitch animation error page
|
|
│ ├── manifest.json # PWA manifest (theme: #A855F7)
|
|
│ ├── robots.txt # Crawler directives
|
|
│ ├── sitemap.xml # 4 pages (/, /tos, /privacy, /api)
|
|
│ ├── icon-dark.svg # Miruro dark mode SVG icon
|
|
│ ├── icon-light.svg # Miruro light mode SVG icon
|
|
│ ├── icon-512x512.png # Miruro app icon
|
|
│ ├── favicon.ico # Classic favicon
|
|
│ ├── apple-touch-icon-180x180.png # iOS home screen icon
|
|
│ ├── og-image.png # OG/Twitter share image
|
|
│ ├── privacy.html # Privacy policy (served at /privacy)
|
|
│ └── tos.html # Terms of service (served at /tos)
|
|
│
|
|
├── assets/ # Scraped Miruro assets
|
|
│ ├── favicons/ # All favicon variants
|
|
│ ├── logos/ # Status page logo
|
|
│ ├── fonts/ # Inter + FontAwesome
|
|
│ └── media/ # Testimonial avatars
|
|
│
|
|
├── docs/ # API documentation
|
|
│ ├── index.md # Overview, quick start, features
|
|
│ ├── endpoints.md # Full API reference (18 endpoints)
|
|
│ ├── streaming.md # Streaming flow guide (3-step)
|
|
│ ├── examples.md # cURL, JavaScript, Python
|
|
│ └── architecture.md # This file
|
|
│
|
|
├── src/
|
|
│ ├── helpers/
|
|
│ │ ├── anilist.js # AniList GraphQL integration
|
|
│ │ ├── pipe.js # Miruro pipe integration
|
|
│ │ └── cache.js # In-memory Map cache with TTL
|
|
│ │
|
|
│ └── routes/
|
|
│ └── apiRoutes.js # All route definitions
|
|
│
|
|
├── test.js # Integration test suite
|
|
├── CHANGELOG.md # Version history
|
|
├── LICENSE # MIT License
|
|
└── README.md # Full API documentation
|
|
```
|
|
|
|
## Tech Stack
|
|
|
|
| Component | Technology |
|
|
|-----------|------------|
|
|
| Runtime | Node.js |
|
|
| Framework | Express.js |
|
|
| Metadata | AniList GraphQL (`graphql.anilist.co`) |
|
|
| Streaming | Miruro pipe (`miruro.{to,ru,bz,tv}/api/secure/pipe`) |
|
|
| Deployment | Vercel (Serverless) |
|
|
| Caching | In-memory Map with 1-5 min TTL |
|
|
| Static Files | Express static middleware |
|
|
|
|
## Request Flow
|
|
|
|
```
|
|
Client Request
|
|
↓
|
|
Vercel Routes (/api/* → server.js)
|
|
↓
|
|
Express Router (apiRoutes.js)
|
|
↓
|
|
Helper (e.g., anilist.js or pipe.js)
|
|
↓
|
|
HTTP Request to AniList GraphQL / Miruro pipe
|
|
↓
|
|
Response decoded (base64url + gzip for pipe)
|
|
↓
|
|
Returns structured JSON
|
|
↓
|
|
Client Response
|
|
```
|
|
|
|
## Streaming Flow
|
|
|
|
```
|
|
/api/episodes/:anilistId
|
|
↓
|
|
Returns: providers with sub/dub episode lists
|
|
↓
|
|
/api/watch/:provider/:anilistId/:category/:slug
|
|
↓
|
|
Returns: streams[] with M3U8 URLs, quality, codec, fansub
|
|
↓
|
|
Play M3U8 in HLS player (hls.js, video.js, native)
|
|
```
|
|
|
|
## Caching Strategy
|
|
|
|
- **Type:** In-memory Map
|
|
- **TTL:** 1-5 minutes depending on endpoint
|
|
- **Max Size:** 100 entries with FIFO eviction
|
|
- **Key:** Full request URL
|
|
- **Behavior:** First request fetches from source, subsequent requests served from cache
|
|
- **Eviction:** Automatic when TTL expires or max size reached
|
|
|
|
## Data Sources
|
|
|
|
### AniList GraphQL
|
|
|
|
- **Endpoint:** `https://graphql.anilist.co`
|
|
- **Data:** Search, suggestions, info, characters, relations, recommendations, filter, schedule
|
|
- **Format:** Standard GraphQL queries
|
|
|
|
### Miruro Pipe
|
|
|
|
- **Endpoint:** `https://miruro.{to,ru}/api/secure/pipe`
|
|
- **Data:** Episodes, streaming sources (M3U8 URLs)
|
|
- **Encoding:** Base64url + gzip compressed request/response
|
|
- **Providers:** kiwi, pewe, bee, bonk, bun, ally, nun, twin, cog, moo, hop, telli
|
|
|
|
## Self-Healing Fallback System (v2.3.0)
|
|
|
|
When Cloudflare blocks streaming requests, the API automatically tries fallback methods in order:
|
|
|
|
1. **Direct** → Mirror rotation across 4 domains (miruro.to, miruro.ru, miruro.bz, miruro.tv)
|
|
2. **ScraperAPI** → Free proxy bypass via ScraperAPI (1K req/month, requires `SCRAPER_API_KEY`)
|
|
3. **FlareSolverr** → Self-hosted browser proxy for full Cloudflare bypass
|
|
|
|
The system tracks success/failure rates per method and auto-rotates to the most reliable option. Check status via `/api/pipe-health`.
|
|
|
|
## Vercel Configuration
|
|
|
|
```json
|
|
{
|
|
"version": 2,
|
|
"builds": [
|
|
{
|
|
"src": "server.js",
|
|
"use": "@vercel/node"
|
|
}
|
|
],
|
|
"routes": [
|
|
{
|
|
"src": "/api/(.*)",
|
|
"dest": "server.js"
|
|
},
|
|
{
|
|
"src": "/(.*)",
|
|
"dest": "server.js"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
- `/api/*` routes to Express for API handling
|
|
- `/*` routes to Express for static file serving
|
|
- Static files served from `process.cwd()` (Vercel serverless compatible)
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `PORT` | `3000` | Server port (Express mode only) |
|
|
| `ALLOWED_ORIGINS` | `*` | Comma-separated allowed origins |
|
|
|
|
## Response Format
|
|
|
|
All API responses follow this structure:
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"results": { ... }
|
|
}
|
|
```
|
|
|
|
Error responses:
|
|
|
|
```json
|
|
{
|
|
"success": false,
|
|
"message": "Error description"
|
|
}
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
| Package | Version | Purpose |
|
|
|---------|---------|---------|
|
|
| express | ^4.21.0 | Web framework |
|
|
| axios | ^1.8.0 | HTTP requests |
|
|
| cors | ^2.8.5 | CORS headers |
|
|
| dotenv | ^16.4.0 | Environment variables |
|
|
|
|
## Cloudflare Worker Architecture (v2.3.1)
|
|
|
|
The Worker edition (`worker.js`) runs the same API on Cloudflare's edge network. Key difference: **streaming endpoints work** because edge-to-edge requests bypass Cloudflare bot detection.
|
|
|
|
### Why Workers Work
|
|
|
|
```
|
|
Vercel (datacenter IP) → miruro.to → Cloudflare WAF → 403 Blocked
|
|
Cloudflare Worker (edge) → miruro.to → Cloudflare internal network → 200 OK
|
|
```
|
|
|
|
### Worker Runtime Differences
|
|
|
|
| Feature | Express (Node.js) | Cloudflare Worker |
|
|
|---------|-------------------|-------------------|
|
|
| HTTP client | axios | native fetch |
|
|
| Decompression | zlib (Node.js) | DecompressionStream (Web API) |
|
|
| Caching | in-memory Map | Workers KV (optional) |
|
|
| npm packages | Yes | No (bundle only) |
|
|
| Cold starts | ~500ms | Zero |
|
|
| CPU limit | None | 10ms (free) / 30s (paid) |
|
|
|
|
### Worker Endpoints (15)
|
|
|
|
| Endpoint | Description |
|
|
|----------|-------------|
|
|
| `GET /api/health` | System health check |
|
|
| `GET /api/search?query=` | Full-text anime search |
|
|
| `GET /api/suggestions?query=` | Autocomplete suggestions |
|
|
| `GET /api/filter?genre=` | Advanced filter |
|
|
| `GET /api/trending` | Trending anime |
|
|
| `GET /api/popular` | Most popular |
|
|
| `GET /api/top` | Top scored |
|
|
| `GET /api/random` | Random anime |
|
|
| `GET /api/info/:id` | Full anime info |
|
|
| `GET /api/anime/:id/characters` | Characters + voice actors |
|
|
| `GET /api/anime/:id/relations` | Related anime |
|
|
| `GET /api/genres` | All genres |
|
|
| `GET /api/episodes/:id` | Episode list (pipe) |
|
|
| `GET /api/watch/:provider/:anilistId/:category/:slug` | Streaming sources (pipe) |
|
|
|
|
### Deploy
|
|
|
|
```bash
|
|
npm install -g wrangler
|
|
wrangler login
|
|
wrangler deploy worker.js --name miruroapi
|
|
```
|