一、问题背景
在将域名 example.com 通过 CNAME 接入 Cloudflare Worker 后,出现以下现象:
- 直接访问 Worker 子域(
*.workers.dev)时,请求可正常进入 Worker,不发生 301 / 308 跳转。 - 通过自定义域名
example.com访问时,请求在浏览器中表现为 301 / 308 重定向,看起来像是 Worker 返回,但实际上 Worker 并未执行。
该问题在调试 Cloudflare Worker 缓存、灰度逻辑时造成了较大困扰。
二、问题现象复现
curl-I http://example.com/?aa=1
返回结果:
HTTP/1.1 301 Moved Permanently
Server: openresty
Location: https://example.com/?aa=1
Strict-Transport-Security: max-age=31536000
关键点:
Server: openresty- 返回的是 301 Moved Permanently
三、根因分析(结论)
该 301 跳转并非 Cloudflare Worker 或 Cloudflare Edge 返回,而是源站 OpenResty(Nginx)在 HTTP 层主动返回的。
访问链路还原
浏览器 / curl
↓
↓
OpenResty(80 端口)
↓
301 → https://example.com
↓
浏览器重新发起 HTTPS 请求
↓
Cloudflare Edge
↓
Cloudflare Worker(此时才会执行)
因此:
- HTTP 请求永远不会进入 Worker
- Worker 只会处理 HTTPS 请求
Worker 子域(*.workers.dev)不存在该问题的原因是:
workers.dev天然为 HTTPS- 不经过自建 OpenResty 源站
四、设计原则(推荐方案)
采用 方案一:HTTP 只负责跳转,HTTPS 全部交由 Cloudflare + Worker 处理。
设计原则如下:
| 层级 | 职责 |
|---|---|
| OpenResty(80) | HTTP → HTTPS 301 跳转 |
| Cloudflare Edge | TLS、WAF、CDN |
| Cloudflare Worker | 灰度逻辑、首页缓存 |
| 源站 | 实际业务处理 |
该方案是当前生产环境中 最清晰、最稳定、最易排查问题 的推荐架构。
五、OpenResty 解决方案(推荐配置)
1️⃣ HTTP(80 端口)配置
目标:只做一件事------跳转到 HTTPS。
j
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
说明:
- 不配置
location - 不做任何代理或业务逻辑
- 尽快完成跳转,减少资源消耗
2️⃣ HTTPS(443 端口)配置(推荐最简兜底)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# HTTPS 层不再做任何重定向逻辑
# 所有访问应由 Cloudflare Worker 接管
location / {
return 444;
}
}
适用场景:
- OpenResty 仅作为兜底源站
- 主要逻辑全部在 Worker 中完成
3️⃣ HTTPS(443)真实回源场景(可选)
若 Worker 部分请求需要回源到 OpenResty(如 /api):
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
前提条件:
- DNS 已开启 Cloudflare 代理(橙云)
- Worker 绑定在该域名的 HTTPS 路由上
六、重要注意事项(避免踩坑)
❌ 不要在 HTTPS Server 中再次做跳转 需要在配置文件中删除
return 301 https://hosthosthostrequest_uri;
rewrite ^ https://hosthosthostrequest_uri permanent;
否则会导致:
- HTTPS → HTTPS 的重复 301 / 308
- Worker 难以排查
- 浏览器缓存异常
⚠️ HSTS 建议只在 Cloudflare 配置
当前响应中已出现:
Strict-Transport-Security: max-age=31536000
建议:
- HSTS 统一由 Cloudflare 管理
- 源站 OpenResty 不再设置
Strict-Transport-Security
七、验证方式(Checklist)
1️⃣ HTTP 请求验证
curl-I http://example.com
期望:
- 状态码:
301 - Server:
openresty
2️⃣ HTTPS 请求验证
curl-I https://example.com/?aa=1
期望:
Server: cloudflare- 包含 Worker 返回的自定义 Header(如
x-demo-cache)
八、总结
- 本次 301 / 308 问题 并非 Worker Bug
- 根因是 OpenResty 在 HTTP 层主动进行 HTTPS 跳转
- 采用"HTTP 跳转 + HTTPS Worker 接管"的方案,是当前最推荐的生产实践