如何通过JavaScript获取cf-ipcountry请求头修改静态站点内容
实现方案
首先明确:前端JavaScript无法直接读取cf-ipcountry请求头——这个字段是Cloudflare在请求处理阶段加到服务端请求上下文里的,不会默认暴露给浏览器端运行的JS,有两种成熟实现方式,优先选第一种,性能最好、改动最小:
方案1:通过Cloudflare Worker在页面返回时注入国家码(推荐)
这个逻辑和你提到的Header鉴权修改返回内容的示例逻辑完全一致,只需要把判断鉴权令牌的步骤换成读取cf-ipcountry字段即可。你已经配置了IP地理定位Worker,只需要修改Worker逻辑,在返回静态HTML内容时,把国家码直接注入到页面的全局变量里即可,不需要额外发请求,也不用改动Github Pages上的原有静态文件。
Worker参考逻辑:
export default { async fetch(request, env) { // 先正常转发请求到Github Pages源站拿静态资源 const response = await fetch(request) // 跳过JS、CSS、图片等非HTML资源,只处理页面返回 const contentType = response.headers.get("content-type") if (!contentType || !contentType.includes("text/html")) { return response } // 从请求头读取国家码,兜底值设为UNKNOWN const countryCode = request.headers.get("cf-ipcountry") || "UNKNOWN" // 拼接注入脚本,把国家码挂到全局window对象上 const injectScript = `<script>window.USER_COUNTRY = "${countryCode}"</script>` // 读取原页面HTML内容,把脚本插到</head>标签前,保证页面自有JS运行前就完成赋值 let html = await response.text() html = html.replace("</head>", `${injectScript}</head>`) // 返回修改后的页面响应 return new Response(html, { headers: response.headers }) } }
部署完Worker后,页面内的JS可以直接读取window.USER_COUNTRY拿到ISO标准两位国家码(比如CN代表中国、US代表美国),直接写弹窗判断逻辑即可:
// 页面DOM加载完成后执行判断 window.addEventListener('DOMContentLoaded', () => { const userCountry = window.USER_COUNTRY // 示例:给美国用户展示专属活动弹窗 if (userCountry === 'US') { alert('Check out our exclusive offer for visitors from the United States!') } // 示例:给欧盟地区用户弹GDPR合规提示 if (['DE', 'FR', 'IT', 'ES', 'NL'].includes(userCountry)) { alert('We use cookies to ensure compliance with EU GDPR regulations.') } })
方案2:通过Worker提供单独的国家码查询接口
如果你不想修改原有HTML的返回内容,可以在Worker里新增一个轻量接口,前端页面加载时主动请求这个接口拿到国家码。
Worker路由判断逻辑参考:
export default { async fetch(request, env) { const url = new URL(request.url) // 匹配国家码查询接口 if (url.pathname === '/api/get-user-country') { const countryCode = request.headers.get("cf-ipcountry") || "UNKNOWN" return new Response(JSON.stringify({ country: countryCode }), { headers: { "Content-Type": "application/json" } }) } // 其余请求正常转发到源站 return fetch(request) } }
前端请求逻辑:
window.addEventListener('DOMContentLoaded', async () => { try { const res = await fetch('/api/get-user-country') const { country } = await res.json() // 后续弹窗判断逻辑和方案1完全一致 } catch (e) { // 降级逻辑:请求失败时默认不弹定制弹窗,或展示通用内容 } })
注意:这个方案会多产生一次HTTP请求,弹窗触发时机晚于页面渲染,容易出现内容闪烁,非特殊情况优先选择注入方案。
内容的提问来源于stack exchange,提问作者tomcritchlow
相关产品推荐
相关产品推荐

