使用Cloudflare Worker实现子路径代理至子域名遇404问题求助
Cloudflare Worker 404问题修复方案
你的代码存在几个关键问题导致转发时返回404,以下是具体问题和修复后的代码:
问题分析
- 路径提取不严谨:当访问
/generator/fontgenerator/about这类带后续路径的地址时,split('/generator/')[1]会得到fontgenerator/about,直接和validSubdomains匹配会失败,因为数组里是纯子域名字符串。 - Host头未修改:原请求的Host头是
rootdomain.com,转发到子域名时未替换为目标子域名,部分站点会因Host不匹配返回404。 - 丢失后续路径:当前代码仅转发到子域名根目录,忽略了原路径中
/generator/subdomain之后的内容,导致子页面无法访问。 - 未处理www域名:代码仅判断了
rootdomain.com,未包含www.rootdomain.com,导致www域名下的请求无法触发转发逻辑。
修复后的代码
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) const allowedHosts = ['rootdomain.com', 'www.rootdomain.com']; // 仅处理根域名和www域名的请求 if (!allowedHosts.includes(url.hostname)) { return fetch(request) } // 处理generator路径 if (url.pathname.startsWith('/generator/')) { // 分割路径,提取子域名和后续路径部分 const pathSegments = url.pathname.replace('/generator/', '').split('/'); const subdomain = pathSegments[0].trim(); const validSubdomains = ['fontgenerator', 'incorrectquotesgenerator', 'randompokemongenerator']; if (!subdomain || !validSubdomains.includes(subdomain)) { return new Response('Not Found', { status: 404 }); } // 拼接完整目标URL,保留后续路径 const targetPath = pathSegments.slice(1).join('/'); const targetUrl = `https://${subdomain}.rootdomain.com/${targetPath}`; // 复制原请求并修改Host头 const modifiedHeaders = new Headers(request.headers); modifiedHeaders.set('Host', `${subdomain}.rootdomain.com`); const modifiedRequest = new Request(targetUrl, { method: request.method, headers: modifiedHeaders, redirect: 'follow', body: request.body, credentials: request.credentials }); return fetch(modifiedRequest); } // 处理image路径 if (url.pathname.startsWith('/image/')) { const pathSegments = url.pathname.replace('/image/', '').split('/'); const action = pathSegments[0].trim(); const validActions = ['removebg']; if (!action || !validActions.includes(action)) { return new Response('Not Found', { status: 404 }); } const targetPath = pathSegments.slice(1).join('/'); const targetUrl = `https://${action}.rootdomain.com/${targetPath}`; const modifiedHeaders = new Headers(request.headers); modifiedHeaders.set('Host', `${action}.rootdomain.com`); const modifiedRequest = new Request(targetUrl, { method: request.method, headers: modifiedHeaders, redirect: 'follow', body: request.body, credentials: request.credentials }); return fetch(modifiedRequest); } // 处理markdown路径 if (url.pathname.startsWith('/markdown/')) { const pathSegments = url.pathname.replace('/markdown/', '').split('/'); const action = pathSegments[0].trim(); const validMarkdownActions = ['markdowntopdf', 'preview']; if (!action || !validMarkdownActions.includes(action)) { return new Response('Not Found', { status: 404 }); } const targetPath = pathSegments.slice(1).join('/'); const targetUrl = `https://${action}.rootdomain.com/${targetPath}`; const modifiedHeaders = new Headers(request.headers); modifiedHeaders.set('Host', `${action}.rootdomain.com`); const modifiedRequest = new Request(targetUrl, { method: request.method, headers: modifiedHeaders, redirect: 'follow', body: request.body, credentials: request.credentials }); return fetch(modifiedRequest); } // 其他路径返回原站点内容 return fetch(request); }
关键修改说明
- 新增
allowedHosts数组,同时处理rootdomain.com和www.rootdomain.com的请求。 - 修改路径提取逻辑:先移除前缀,再用
split('/')分割,提取第一个元素作为子域名/动作,剩余部分拼接为后续路径。 - 转发请求时修改
Host头为目标子域名,确保目标服务器能正确识别请求。 - 保留原请求的
body、credentials等参数,兼容POST等请求方法。 - 默认路径改为返回原请求内容,而非固定提示文本,更符合实际站点需求。
内容的提问来源于stack exchange,提问作者edwin_uestc
相关产品推荐
相关产品推荐

