将带ProxyPreserveHost的Apache反向代理转为Cloudflare Workers脚本
解决方案:Apache ProxyPreserveHost 转 Cloudflare Workers 脚本
核心问题解析
Fetch API 能否覆盖 Host 头?
完全可以,Cloudflare Workers 作为边缘执行环境,没有浏览器端 Fetch 的 Host 头限制。你遇到的 500 错误大概率是请求构造不完整(比如遗漏请求体、必要请求头),而非 Host 头本身的限制。修改 Host 头后权限拒绝?
这是因为目标服务器(wordpress.example.com)的配置限制——它只接受 Host 头为自身域名的请求。Apache 的ProxyPreserveHost是把客户端的 Host(example.com)传递给后端,此时需要后端服务(WordPress)允许这个 Host 访问,否则会触发权限拦截。
正确的 Workers 脚本实现
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) // 匹配 /blog 路径的请求 if (url.pathname.startsWith('/blog')) { // 构造目标地址:保留原请求的路径和查询参数,替换为后端域名 const targetUrl = new URL(`${url.pathname}${url.search}`, 'http://wordpress.example.com') // 复制原请求头,设置 Host 为原请求的 Host(对应 ProxyPreserveHost 逻辑) const modifiedHeaders = new Headers(request.headers) modifiedHeaders.set('Host', url.host) // 构造完整的代理请求,保留原请求的方法、请求体等 const proxyRequest = new Request(targetUrl, { method: request.method, headers: modifiedHeaders, body: request.body, redirect: 'follow', // 若 wordpress.example.com 托管在 Cloudflare,可添加 resolveOverride 确保解析正确 // cf: { resolveOverride: 'wordpress.example.com' } }) try { const response = await fetch(proxyRequest) // 返回后端响应,保留状态码、响应头和响应体 return new Response(response.body, { status: response.status, statusText: response.statusText, headers: response.headers }) } catch (err) { return new Response(`代理错误: ${err.message}`, { status: 500 }) } } // 非 /blog 路径直接转发原请求 return fetch(request) }
关键调整说明
- 请求完整性:复制原请求的方法、请求体、所有请求头(仅修改 Host),避免因遗漏必要信息导致后端返回 500。
- Host 头传递:严格对应 Apache
ProxyPreserveHost的逻辑,把客户端请求的 Host(example.com)传给后端。 - 后端适配:需要在 WordPress 后台配置允许 example.com 作为访问域名:
- 修改
wp-config.php,添加:define('WP_HOME', 'http://example.com/blog'); define('WP_SITEURL', 'http://wordpress.example.com/blog'); - 或在 WordPress 设置中,把站点地址(Site Address)改为
http://example.com/blog。
- 修改
额外注意事项
- 如果后端使用 HTTPS,把目标 URL 的协议改为
https://,并确保 SSL 证书有效。 - 若遇到跨域问题,可在响应头中添加 CORS 相关配置,比如:
const modifiedResponseHeaders = new Headers(response.headers) modifiedResponseHeaders.set('Access-Control-Allow-Origin', url.origin) return new Response(response.body, { headers: modifiedResponseHeaders })
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

