Extensible NestJS reverse proxy for the Anixart API.
The server forwards the client's original method, path, query string, body, and API-specific headers to a configurable upstream. Request and response extensions can then modify selected calls without duplicating all 275 API routes.
- Node.js 20 or newer
- npm 10 or newer
cp .env.example .env
npm install
npm run start:devProduction:
npm run build
npm startThe default upstream is https://api-s.anixsekai.com/. Point the Android
client's API_BASE_URL to this server.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Listening port |
UPSTREAM_URL |
https://api-s.anixsekai.com/ |
Original API base URL |
UPSTREAM_TIMEOUT_MS |
15000 |
Upstream timeout |
MAX_BODY_SIZE |
50mb |
Maximum request body size |
TRUST_PROXY |
false |
Enable Express trust proxy |
INSTANCE_PUBLIC_URL |
http://localhost:3000 |
Public URL embedded into generated media links |
MEDIA_TOKEN_SECRET |
generated | Secret used to sign parser and HLS URLs |
MEDIA_TOKEN_TTL_SECONDS |
21600 |
Lifetime of signed media URLs |
OUTBOUND_TIMEOUT_MS |
10000 |
Timeout for media/source requests |
ALLOW_PRIVATE_MEDIA_URLS |
false |
Allow private destination addresses; intended only for tests |
CUSTOM_SOURCES_ENABLED |
true |
Enable episode response hooks |
YUMMYANIME_ENABLED |
true |
Enable the first custom source provider |
ALLOHA_ENABLED |
false |
Enable the legacy Alloha parser; its old transport is currently unavailable |
AKSOR_ENABLED |
false |
Enable the legacy Aksor parser; its former inline videoUrl is currently unavailable |
ANITYPE_ENABLED |
false |
Enable AniType parser when a token is configured |
ANITYPE_TOKEN |
empty | AniType bearer token |
The first source hook enriches the standard episode flow:
GET /episode/:releaseId/:typeIdadds supported YummyAnime players;GET /episode/:releaseId/:typeId/:sourceIdreturns custom episodes;GET /episode/target/:releaseId/:sourceId/:positionreturns one episode;GET /cp/parser/:typeresolves a signed player URL into direct links.
The currently active parser is CVH; its HLS master is routed through the
signed HLS proxy while direct quality links remain available. Alloha and
Aksor are retained behind disabled feature flags because their former
transports were removed. AniType is registered only when both its feature flag
and token are set. Only active parser types are exposed to the client.
GET /hlsp/:token/:file proxies signed HLS resources. Master/media playlists,
relative segments, encryption keys, Range requests, and nested playlists are
supported. Tokens are HMAC-signed by the server, so the endpoint cannot be used
as an arbitrary public URL proxy.
Extensions implement ProxyExtension and may:
- change a request in
beforeRequest; - change an upstream response in
afterResponse; - observe upstream failures in
onError; - select routes with
matches.
Register a new extension in src/proxy/proxy.module.ts:
@Injectable()
export class ReleaseExtension implements ProxyExtension {
readonly name = 'Release enrichment';
matches(request: ProxyRequestContext): boolean {
return request.method === 'GET'
&& /^\/release\/\d+/.test(request.upstreamUrl.pathname);
}
afterResponse(response: ProxyResponseContext): ProxyResponseContext {
const data = JSON.parse(response.body.toString('utf8'));
data.release.custom_field = 'value';
response.body = Buffer.from(JSON.stringify(data));
response.headers.delete('content-length');
return response;
}
}Add the class as a provider and append it to the array returned by the
PROXY_EXTENSIONS provider.
See docs/API_ANALYSIS.md for details extracted from the current APK.
See docs/ALLOHA_PROTOCOL.md for notes on the current Alloha browser session and why the legacy direct-link transport remains disabled.
The previous Express implementation and experimental media parsers are retained
under legacy/express as migration references. They are not part of the NestJS
build.