chore: add host info of relevant URL to all errors
This commit is contained in:
parent
77164dfaa7
commit
cc3d30be2f
9 changed files with 73 additions and 41 deletions
|
|
@ -1,11 +1,13 @@
|
|||
export class HttpError extends Error {
|
||||
public readonly url: URL;
|
||||
public readonly status: number;
|
||||
public readonly statusText: string;
|
||||
public readonly headers: Record<string, string[] | string | undefined>;
|
||||
|
||||
public constructor(status: number, statusText: string, headers: Record<string, string[] | string | undefined>) {
|
||||
public constructor(url: URL, status: number, statusText: string, headers: Record<string, string[] | string | undefined>) {
|
||||
super();
|
||||
|
||||
this.url = url;
|
||||
this.status = status;
|
||||
this.statusText = statusText;
|
||||
this.headers = headers;
|
||||
|
|
|
|||
|
|
@ -1 +1,9 @@
|
|||
export class QueueIsFullError extends Error {}
|
||||
export class QueueIsFullError extends Error {
|
||||
public readonly url: URL;
|
||||
|
||||
public constructor(url: URL) {
|
||||
super();
|
||||
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,9 @@
|
|||
export class TimeoutError extends Error {}
|
||||
export class TimeoutError extends Error {
|
||||
public readonly url: URL;
|
||||
|
||||
public constructor(url: URL) {
|
||||
super();
|
||||
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
export class TooManyRequestsError extends Error {
|
||||
public readonly url: URL;
|
||||
public readonly retryAfter: number;
|
||||
|
||||
public constructor(retryAfter: number) {
|
||||
public constructor(url: URL, retryAfter: number) {
|
||||
super();
|
||||
|
||||
this.url = url;
|
||||
this.retryAfter = retryAfter;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,9 @@
|
|||
export class TooManyTimeoutsError extends Error {}
|
||||
export class TooManyTimeoutsError extends Error {
|
||||
public readonly url: URL;
|
||||
|
||||
public constructor(url: URL) {
|
||||
super();
|
||||
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,46 +21,50 @@ export const logErrorAndReturnNiceString = (ctx: Context, logger: winston.Logger
|
|||
return '⚠️ MediaFlow Proxy authentication failed. Please set the correct password.';
|
||||
}
|
||||
|
||||
logger.warn(`${source}: Request to ${error.url.href} was blocked, reason: ${error.reason}, headers: ${JSON.stringify(error.headers)}.`, ctx);
|
||||
logger.warn(`${source}: Request to ${error.url} was blocked, reason: ${error.reason}, headers: ${JSON.stringify(error.headers)}.`, ctx);
|
||||
|
||||
return `⚠️ Request was blocked. Reason: ${error.reason}`;
|
||||
return `⚠️ Request to ${error.url.host} was blocked. Reason: ${error.reason}`;
|
||||
}
|
||||
|
||||
if (error instanceof TooManyRequestsError) {
|
||||
logger.warn(`${source}: Rate limited for ${error.retryAfter} seconds.`, ctx);
|
||||
logger.warn(`${source}: Request to ${error.url} was rate limited for ${error.retryAfter} seconds.`, ctx);
|
||||
|
||||
return '🚦 Request was rate-limited. Please try again later or consider self-hosting.';
|
||||
return `🚦 Request to ${error.url.host} was rate-limited. Please try again later or consider self-hosting.`;
|
||||
}
|
||||
|
||||
if (error instanceof TooManyTimeoutsError) {
|
||||
logger.warn(`${source}: Too many timeouts.`, ctx);
|
||||
logger.warn(`${source}: Too many timeouts when requesting ${error.url}.`, ctx);
|
||||
|
||||
return '🚦 Too many recent timeouts. Please try again later.';
|
||||
return `🚦 Too many recent timeouts when requesting ${error.url.host}. Please try again later.`;
|
||||
}
|
||||
|
||||
if (
|
||||
error instanceof TimeoutError
|
||||
|| (error instanceof DOMException && ['AbortError', 'TimeoutError'].includes(error.name)) // sometimes this gets through, no idea why..
|
||||
) {
|
||||
if (error instanceof TimeoutError) {
|
||||
logger.warn(`${source}: Request to ${error.url} timed out.`, ctx);
|
||||
|
||||
return `🐢 Request to ${error.url.host} timed out.`;
|
||||
}
|
||||
|
||||
if (error instanceof DOMException && ['AbortError', 'TimeoutError'].includes(error.name)) {
|
||||
// sometimes this gets through, no idea why..
|
||||
logger.warn(`${source}: Request timed out.`, ctx);
|
||||
|
||||
return '🐢 Request timed out.';
|
||||
}
|
||||
|
||||
if (error instanceof QueueIsFullError) {
|
||||
logger.warn(`${source}: Request queue is full.`, ctx);
|
||||
logger.warn(`${source}: Request queue for ${error.url.host} is full.`, ctx);
|
||||
|
||||
return '⏳ Request queue is full. Please try again later or consider self-hosting.';
|
||||
return `⏳ Request queue for ${error.url.host} is full. Please try again later or consider self-hosting.`;
|
||||
}
|
||||
|
||||
if (error instanceof HttpError) {
|
||||
logger.error(`${source}: HTTP status ${error.status} (${error.statusText}), headers: ${JSON.stringify(error.headers)}, stack: ${error.stack}.`, ctx);
|
||||
logger.error(`${source}: Error when requesting url ${error.url}, HTTP status ${error.status} (${error.statusText}), headers: ${JSON.stringify(error.headers)}, stack: ${error.stack}.`, ctx);
|
||||
|
||||
if (error.status >= 500) {
|
||||
return `❌ Remote server has issues. We can't fix this, please try later again.`;
|
||||
return `❌ Remote server ${error.url.host} has issues. We can't fix this, please try later again.`;
|
||||
}
|
||||
|
||||
return `❌ Request failed with status ${error.status} (${error.statusText}). Request-id: ${ctx.id}.`;
|
||||
return `❌ Request to ${error.url.host} failed with status ${error.status} (${error.statusText}). Request-id: ${ctx.id}.`;
|
||||
}
|
||||
|
||||
const cause = (error as Error & { cause?: unknown }).cause;
|
||||
|
|
|
|||
|
|
@ -213,10 +213,10 @@ export class Fetcher {
|
|||
await this.rateLimitedCache.set<true>(url.host, true, retryAfter * 1000);
|
||||
}
|
||||
|
||||
throw new TooManyRequestsError(retryAfter);
|
||||
throw new TooManyRequestsError(url, retryAfter);
|
||||
}
|
||||
|
||||
throw new HttpError(httpCacheItem.status, httpCacheItem.statusText, httpCacheItem.headers);
|
||||
throw new HttpError(url, httpCacheItem.status, httpCacheItem.statusText, httpCacheItem.headers);
|
||||
};
|
||||
|
||||
private determineCacheKey(url: URL, init?: CustomRequestInit): string {
|
||||
|
|
@ -308,12 +308,12 @@ export class Fetcher {
|
|||
return await this.fetchWithTimeout(ctx, url, { ...init, queueLimit: 1 }, ++tryCount);
|
||||
}
|
||||
|
||||
throw new TooManyRequestsError((isRateLimitedRaw.expires as number - Date.now()) / 1000);
|
||||
throw new TooManyRequestsError(url, (isRateLimitedRaw.expires as number - Date.now()) / 1000);
|
||||
}
|
||||
|
||||
const timeouts = (await this.timeoutsCountCache.get<number>(url.host)) ?? 0;
|
||||
if (timeouts >= (init?.timeoutsCountThrow ?? this.DEFAULT_TIMEOUTS_COUNT_THROW)) {
|
||||
throw new TooManyTimeoutsError();
|
||||
throw new TooManyTimeoutsError(url);
|
||||
}
|
||||
|
||||
let response;
|
||||
|
|
@ -335,7 +335,7 @@ export class Fetcher {
|
|||
|
||||
if (error instanceof DOMException && ['AbortError', 'TimeoutError'].includes(error.name)) {
|
||||
await this.increaseTimeoutsCount(url);
|
||||
throw new TimeoutError();
|
||||
throw new TimeoutError(url);
|
||||
}
|
||||
|
||||
if (tryCount < 3) {
|
||||
|
|
@ -393,7 +393,7 @@ export class Fetcher {
|
|||
let sem = this.semaphores.get(url.host);
|
||||
|
||||
if (!sem) {
|
||||
sem = withTimeout(new Semaphore(queueLimit), queueTimeout, new QueueIsFullError());
|
||||
sem = withTimeout(new Semaphore(queueLimit), queueTimeout, new QueueIsFullError(url));
|
||||
this.semaphores.set(url.host, sem);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new TooManyRequestsError(10),
|
||||
error: new TooManyRequestsError(new URL('https://example.com'), 10),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
@ -164,7 +164,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new TooManyTimeoutsError(),
|
||||
error: new TooManyTimeoutsError(new URL('https://example.com')),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
@ -195,7 +195,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example2.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new TimeoutError(),
|
||||
error: new TimeoutError(new URL('https://example2.com')),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
@ -206,7 +206,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example3.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new QueueIsFullError(),
|
||||
error: new QueueIsFullError(new URL('https://example3.com')),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
@ -217,7 +217,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example4.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new HttpError(500, 'Internal Server Error', { 'x-foo': 'bar' }),
|
||||
error: new HttpError(new URL('https://example4.com'), 500, 'Internal Server Error', { 'x-foo': 'bar' }),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
@ -228,7 +228,7 @@ describe('resolve', () => {
|
|||
url: new URL('https://example5.com'),
|
||||
format: Format.unknown,
|
||||
isExternal: true,
|
||||
error: new HttpError(418, 'I\'m a tea pot', { 'x-foo': 'bar' }),
|
||||
error: new HttpError(new URL('https://example5.com'), 418, 'I\'m a tea pot', { 'x-foo': 'bar' }),
|
||||
label: 'hoster.com',
|
||||
sourceId: '',
|
||||
meta: {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example5.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
❌ Request failed with status 418 (I'm a tea pot). Request-id: test.",
|
||||
❌ Request to example5.com failed with status 418 (I'm a tea pot). Request-id: test.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -44,7 +44,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example4.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
❌ Remote server has issues. We can't fix this, please try later again.",
|
||||
❌ Remote server example4.com has issues. We can't fix this, please try later again.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -53,7 +53,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example3.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
⏳ Request queue is full. Please try again later or consider self-hosting.",
|
||||
⏳ Request queue for example3.com is full. Please try again later or consider self-hosting.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -62,7 +62,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example2.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
🐢 Request timed out.",
|
||||
🐢 Request to example2.com timed out.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -80,7 +80,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
🚦 Too many recent timeouts. Please try again later.",
|
||||
🚦 Too many recent timeouts when requesting example.com. Please try again later.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -89,7 +89,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
🚦 Request was rate-limited. Please try again later or consider self-hosting.",
|
||||
🚦 Request to example.com was rate-limited. Please try again later or consider self-hosting.",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -98,7 +98,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
⚠️ Request was blocked. Reason: unknown",
|
||||
⚠️ Request to example.com was blocked. Reason: unknown",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -116,7 +116,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
⚠️ Request was blocked. Reason: cloudflare_censor",
|
||||
⚠️ Request to example.com was blocked. Reason: cloudflare_censor",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
@ -125,7 +125,7 @@ exports[`resolve adds error info 2`] = `
|
|||
"externalUrl": "https://example.com/",
|
||||
"name": "WebStreamr 🇩🇪",
|
||||
"title": "🔗 hoster.com
|
||||
⚠️ Request was blocked. Reason: cloudflare_challenge",
|
||||
⚠️ Request to example.com was blocked. Reason: cloudflare_challenge",
|
||||
},
|
||||
{
|
||||
"behaviorHints": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue