mirror of
https://github.com/Shineii86/AniKotoAPI.git
synced 2026-10-22 10:55:10 +00:00
fix: detect upstream API errors in stream endpoint to prevent null URL responses
- Added upstream error detection in streamInfo.extractor.js (status >= 400) - Added non-JSON error string detection from upstream API - Updated streamInfo.controller.js to return HTTP 502 for upstream failures - Fixes /api/stream returning null URL when upstream returns error responses
This commit is contained in:
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.2.2] - 2026-08-14
|
||||
|
||||
### Fixed
|
||||
- **CRITICAL**: Fixed `/api/stream` returning `null` URL when upstream API returns error responses (e.g. `{status: 500, result: "Bad request"}`) — extractor now detects upstream error status codes and throws meaningful errors instead of silently returning null
|
||||
- Fixed `streamInfo.extractor.js` `extractStreamInfo` to detect upstream API error responses (`data.status >= 400`) and throw descriptive errors
|
||||
- Fixed `streamInfo.extractor.js` `extractStreamInfo` to detect non-JSON error strings from upstream API (e.g. "Bad request") and throw errors instead of silently swallowing them
|
||||
- Fixed `streamInfo.extractor.js` `extractServerList` to detect upstream API error responses and throw descriptive errors
|
||||
- Fixed `streamInfo.controller.js` `getStreamInfo` to return HTTP 502 (Bad Gateway) with error message for upstream API failures instead of silently returning null URL
|
||||
- Fixed `streamInfo.controller.js` `getServerList` to properly propagate upstream errors via error handler
|
||||
|
||||
## [2.2.1] - 2026-08-12
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -53,7 +53,12 @@ const getStreamInfo = async (req, res, next) => {
|
||||
if (cached) {
|
||||
return res.json({ success: true, results: cached });
|
||||
}
|
||||
const data = await extractStreamInfo(id);
|
||||
let data;
|
||||
try {
|
||||
data = await extractStreamInfo(id);
|
||||
} catch (upstreamError) {
|
||||
return res.status(502).json({ success: false, message: `Upstream API error: ${upstreamError.message}` });
|
||||
}
|
||||
if (!data.url) {
|
||||
return res.status(404).json({ success: false, message: "Stream URL not found for this link ID", results: data });
|
||||
}
|
||||
|
||||
@@ -59,11 +59,27 @@ const extractStreamInfo = async (linkId, watchSlug = null) => {
|
||||
try { data = JSON.parse(raw); } catch { data = {}; }
|
||||
}
|
||||
|
||||
// NOTE: Detect upstream API error responses (e.g. {status: 500, result: "Bad request"})
|
||||
if (data && typeof data === "object" && data.status && Number(data.status) >= 400) {
|
||||
throw new Error(`Upstream API error (${data.status}): ${data.result || "Unknown error"}`);
|
||||
}
|
||||
|
||||
if (!data || !data.result) {
|
||||
return { linkId, url: null, type: null, skipData: null };
|
||||
}
|
||||
|
||||
const result = typeof data.result === "string" ? (() => { try { return JSON.parse(data.result); } catch { return {}; } })() : data.result;
|
||||
// NOTE: If result is a non-JSON string (error message), treat as upstream failure
|
||||
const result = typeof data.result === "string"
|
||||
? (() => {
|
||||
try { return JSON.parse(data.result); }
|
||||
catch {
|
||||
if (!data.result.startsWith("{") && !data.result.startsWith("[")) {
|
||||
throw new Error(`Upstream returned invalid data: ${data.result}`);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
})()
|
||||
: data.result;
|
||||
|
||||
const streamUrl = result.url || null;
|
||||
const streamType = streamUrl?.includes(".m3u8") ? "hls" : streamUrl ? "mp4" : null;
|
||||
@@ -115,6 +131,12 @@ const extractServerList = async (episodeIds, watchSlug = null) => {
|
||||
if (typeof raw === "string") {
|
||||
try { parsed = JSON.parse(raw); } catch { parsed = {}; }
|
||||
}
|
||||
|
||||
// NOTE: Detect upstream API error responses
|
||||
if (parsed && typeof parsed === "object" && parsed.status && Number(parsed.status) >= 400) {
|
||||
throw new Error(`Upstream API error (${parsed.status}): ${parsed.result || "Unknown error"}`);
|
||||
}
|
||||
|
||||
const html = parsed?.result || "";
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user