From 6f092a6b1a84a97790e83f0a1bc0aad6acf0d552 Mon Sep 17 00:00:00 2001 From: trinhthiminh650-tech Date: Sat, 15 Aug 2026 01:02:02 +0800 Subject: [PATCH] fix(browser): probe embed signals via GET fallback when HEAD omits them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some servers (e.g. aliyun consoles) answer HEAD without the X-Frame-Options / Content-Security-Policy headers that only their GET response carries. The embeddability probe then wrongly reported the site as embeddable, leaving the plain iframe to surface the browser's misleading "refused to connect" error (the site actually forbids framing via frame-ancestors). Retry once as GET when both embed signals are absent (the body is discarded — only headers matter), mirroring the existing 405/501 HEAD fallback. The client then shows the friendly embed-refusal panel with an "open in browser" action instead of the misleading connection error. --- src/index.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/index.ts b/src/index.ts index f9e0622..554c995 100644 --- a/src/index.ts +++ b/src/index.ts @@ -393,6 +393,17 @@ function buildApi( if (response.status === 405 || response.status === 501) { response = await fetch(parsed, { method: 'GET', redirect: 'follow', signal: controller.signal }) } + // Some servers (e.g. aliyun consoles) answer HEAD without the + // X-Frame-Options / CSP headers that only their GET response + // carries. Without those signals the embeddability check below + // would wrongly report the site as embeddable and the plain iframe + // would surface the browser's misleading "refused to connect". + // Retry once as GET when both signals are absent (body discarded). + const hasEmbedSignals = response.headers.get('content-security-policy') !== null + || response.headers.get('x-frame-options') !== null + if (!hasEmbedSignals && response.status !== 405 && response.status !== 501) { + response = await fetch(parsed, { method: 'GET', redirect: 'follow', signal: controller.signal }) + } const csp = response.headers.get('content-security-policy') const frameAncestors = extractFrameAncestors(csp) const xFrameOptions = response.headers.get('x-frame-options')