Cloudflare Workers:仅首次访问地理重定向 后续遵循会话语言
Cloudflare Workers 首次访问地域重定向改造方案
核心改造逻辑
现有代码未做访问状态校验,所有请求都会直接触发重定向,且使用301永久重定向会被浏览器缓存,进一步导致跳转逻辑异常。改造通过Cookie做状态标记,逻辑如下:
- 所有请求进入时先校验是否存在专属标识Cookie
geo_redirected- 存在该Cookie:说明用户已经完成首次跳转/手动选择过站点版本,直接放行原请求,不做任何地域强制跳转
- 不存在该Cookie:匹配IP归属地得到目标站点地址
- 如果当前请求地址已经和目标地址一致:直接返回源站内容,同时写入标识Cookie,避免死循环
- 如果当前请求地址和目标地址不一致:返回302临时重定向到目标地址,同时在响应头写入标识Cookie,后续用户访问将不再触发强制跳转
Cookie配置说明
标识Cookie采用以下配置,兼顾可用性和浏览器兼容性:
- Cookie名:
geo_redirected - 值:
1(标记已完成首次跳转) - 有效期:
Max-Age=2592000即30天,可根据需求自行调整时长 - 生效范围:
Path=/全站所有路径生效 - 安全属性:
SameSite=Lax适配现代浏览器跨站安全规则
改造后完整代码
// 各国家/地区对应跳转路径 var sg_countries = ['SG', 'TH', 'MY', 'VN', 'RI', 'RP', 'LA', 'BN']; var jp_countries = ['JP']; var gr_countries = ['GR']; var kr_countries = ['KR']; var zh_sg_countries = ['TW', 'HK', 'CN']; // 标识Cookie配置 const REDIRECT_COOKIE = 'geo_redirected=1; Max-Age=2592000; Path=/; SameSite=Lax'; addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) function inArray(needle, haystack) { var length = haystack.length; for (var i = 0; i < length; i++) { if (haystack[i] == needle) return true; } return false; } function mapCountry(country_code) { if (inArray(country_code, sg_countries)) { return 'https://ofdreams.com/sg'; } if (inArray(country_code, jp_countries)) { return 'https://ofdreams.com/jp'; } if (inArray(country_code, gr_countries)) { return 'https://ofdreams.com/gr'; } if (inArray(country_code, kr_countries)) { return 'https://ofdreams.com/kr'; } if (inArray(country_code, zh_sg_countries)) { return 'https://ofdreams.com/zh-sg'; } // 默认跳转至US站点 return 'https://ofdreams.com'; } async function handleRequest(request) { const url = new URL(request.url); // 读取请求携带的Cookie const cookie = request.headers.get('Cookie') || ''; // 存在已跳转标识,直接放行原请求 if (cookie.includes('geo_redirected=1')) { return fetch(request); } // 匹配当前IP归属地对应的目标地址 const targetUrl = mapCountry(request.headers.get('CF-IPCountry')); const target = new URL(targetUrl); // 当前访问路径已经和目标地域路径一致,直接返回内容并写入Cookie if (url.pathname === target.pathname && url.origin === target.origin) { const response = await fetch(request); const newResponse = new Response(response.body, response); newResponse.headers.append('Set-Cookie', REDIRECT_COOKIE); return newResponse; } // 首次访问且路径不匹配,返回302临时跳转并写入Cookie return new Response('', { status: 302, headers: { 'Location': targetUrl, 'Set-Cookie': REDIRECT_COOKIE, 'Cache-Control': 'no-store' // 禁止浏览器缓存跳转响应,避免异常 } }) }
注意事项
- 原代码使用的301永久重定向会被浏览器本地强缓存,测试前请清空浏览器缓存,避免旧缓存逻辑影响效果
- 如果站点存在手动切换语言/站点版本的功能,只需要在用户手动切换时,重新设置该Cookie(可将值改为用户选择的版本标识),即可完全尊重用户自主选择,不会再触发地域强制跳转
- 如果需要Cookie仅在HTTPS环境下生效,可在Cookie配置中追加
Secure属性
内容的提问来源于stack exchange,提问作者tecne
相关产品推荐
相关产品推荐

