chore: handle cloudflare 451 censor block, show block reasons

This commit is contained in:
WebStreamr 2025-07-21 19:35:52 +00:00
parent 114d296fe3
commit 51b9104f07
No known key found for this signature in database
6 changed files with 54 additions and 5 deletions

View file

@ -32,6 +32,7 @@ export enum CountryCode {
export enum BlockedReason {
cloudflare_challenge = 'cloudflare_challenge',
flaresolverr_failed = 'flaresolverr_failed',
cloudflare_censor = 'cloudflare_censor',
media_flow_proxy_auth = 'media_flow_proxy_auth',
unknown = 'unknown',
}

View file

@ -149,6 +149,19 @@ describe('fetch', () => {
}
});
test('converts cloudflare 451 to custom BlockedError', async () => {
const mockPool = mockAgent.get('https://some-cloudflare-forbidden-url.test');
mockPool.intercept({ path: '/' }).reply(451);
try {
await fetcher.text(ctx, new URL('https://some-cloudflare-forbidden-url.test/'));
fail();
} catch (error) {
expect(error).toBeInstanceOf(BlockedError);
expect(error).toMatchObject({ reason: BlockedReason.cloudflare_censor });
}
});
test('converts MediaFlow Proxy forbidden to custom BlockedError', async () => {
const mockPool = mockAgent.get('https://media-flow-proxy-forbidden-url.test');
mockPool.intercept({ path: '/' }).reply(403);

View file

@ -171,6 +171,10 @@ export class Fetcher {
throw new BlockedError(BlockedReason.unknown, httpCacheItem.policy.responseHeaders());
}
if (httpCacheItem.status === 451) {
throw new BlockedError(BlockedReason.cloudflare_censor, httpCacheItem.policy.responseHeaders());
}
if (httpCacheItem.status === 429) {
const retryAfter = parseInt(`${httpCacheItem.policy.responseHeaders()['retry-after']}`);
if (!isNaN(retryAfter)) {

View file

@ -103,6 +103,17 @@ describe('resolve', () => {
countryCodes: [CountryCode.de],
},
},
{
url: new URL('https://example.com'),
format: Format.unknown,
isExternal: true,
error: new BlockedError(BlockedReason.cloudflare_censor, {}),
label: 'hoster.com',
sourceId: '',
meta: {
countryCodes: [CountryCode.de],
},
},
{
url: new URL('https://example.com'),
format: Format.unknown,

View file

@ -175,13 +175,15 @@ export class StreamResolver {
if (error instanceof BlockedError) {
if (error.reason === BlockedReason.cloudflare_challenge) {
this.logger.warn(`${source}: Request was blocked via Cloudflare challenge.`, ctx);
} else if (error.reason === BlockedReason.cloudflare_censor) {
this.logger.warn(`${source}: Request was censored by Cloudflare.`, ctx);
} else if (error.reason === BlockedReason.media_flow_proxy_auth) {
return '⚠️ MediaFlow Proxy authentication failed. Please set the correct password.';
} else {
this.logger.warn(`${source}: Request was blocked, headers: ${JSON.stringify(error.headers)}.`, ctx);
}
return '⚠️ Request was blocked.';
return `⚠️ Request was blocked. Reason: ${error.reason}`;
}
if (error instanceof TooManyRequestsError) {

View file

@ -28,7 +28,16 @@ exports[`resolve adds error info 1`] = `
"externalUrl": "http://localhost/",
"name": "WebStreamr 🇩🇪",
"title": "🔗 hoster.com
⚠️ Request was blocked.",
⚠️ Request was blocked. Reason: cloudflare_challenge",
},
{
"behaviorHints": {
"notWebReady": true,
},
"externalUrl": "http://localhost/",
"name": "WebStreamr 🇩🇪",
"title": "🔗 hoster.com
⚠️ Request was blocked. Reason: cloudflare_censor",
},
{
"behaviorHints": {
@ -46,7 +55,7 @@ exports[`resolve adds error info 1`] = `
"externalUrl": "http://localhost/",
"name": "WebStreamr 🇩🇪",
"title": "🔗 hoster.com
⚠️ Request was blocked.",
⚠️ Request was blocked. Reason: unknown",
},
{
"behaviorHints": {
@ -143,7 +152,16 @@ exports[`resolve adds error info 2`] = `
"externalUrl": "https://example.com/",
"name": "WebStreamr 🇩🇪 ⚠️ external",
"title": "🔗 hoster.com
⚠️ Request was blocked.",
⚠️ Request was blocked. Reason: cloudflare_challenge",
},
{
"behaviorHints": {
"notWebReady": true,
},
"externalUrl": "https://example.com/",
"name": "WebStreamr 🇩🇪 ⚠️ external",
"title": "🔗 hoster.com
⚠️ Request was blocked. Reason: cloudflare_censor",
},
{
"behaviorHints": {
@ -161,7 +179,7 @@ exports[`resolve adds error info 2`] = `
"externalUrl": "https://example.com/",
"name": "WebStreamr 🇩🇪 ⚠️ external",
"title": "🔗 hoster.com
⚠️ Request was blocked.",
⚠️ Request was blocked. Reason: unknown",
},
{
"behaviorHints": {