边缘判定与脚本对接
把流量留在自己的网站上,用官方 PHP 包、Cloudflare Worker 或 Cloudflare Pages 接入平台判定:按访客规则放行、出页、打开本站路径、跳转或只回状态码。
访客访问你自己的网站时,官方脚本向平台询问结果,再按动作放行、出页、打开本站路径、302 跳转或只回状态码。域名和网站不必迁到平台。
官方提供三份脚本包,判定行为对齐,按站点环境任选其一:
- PHP 包(
{name}-php.zip):传统主机或虚拟主机,使用 PHP 8.3 时放到站点同目录。始终一包,Apache / Nginx 只是同包内的伪静态示例 - Cloudflare Worker(
{name}-cf-worker.zip):源站已接入 Cloudflare 并绑 Worker 路由时用 - Cloudflare Pages(
{name}-cf-pages.zip):站点在 Cloudflare Pages 上时用。必须带_routes.json
Worker 与 Pages 同一 Workers 运行时,但挂法不同,控制台分两个 zip 下载。不要把 Worker 与 Pages 中间件挂在同一路由。
适用场景
- 希望域名和网站留在自己这边
- 用官方脚本接入判定,不必自己对接接口
平台托管投放(把域名指到平台)仍然可用。
怎么选脚本
| 站点环境 | 用哪个 |
|---|---|
| 自有服务器或虚拟主机,PHP 8.3 | {name}-php.zip |
| 站点已接入 Cloudflare(源站 + 路由) | {name}-cf-worker.zip |
| 站点在 Cloudflare Pages | {name}-cf-pages.zip |
三者都调用同一套判定接口(POST /v1/decision,Bearer)。脚本本身不做 PHP 版本探测。
怎么用
- 开通边缘判定,并确认套餐档位
- 在控制台「边缘对接」选择规则模板,并配置通过 / 拦截时的动作
- 按环境下载官方 PHP 包、Cloudflare Worker 或 Cloudflare Pages(三者并列,任选其一)
- 按下方对应步骤部署
- 访客访问该站点时,脚本按返回结果执行
场景配置
控制台「边缘对接」里每个场景对应一把密钥、一套规则模板和一组动作。字段如下。
| 字段 | 取值 | 说明 |
|---|---|---|
name | 1–128 字符 | 场景名称 |
rule_template_id | 必填 | 账号内可见的广告规则模板(国家、UA、IP 等) |
pass_action | allow / html / redirect / path | 规则通过时的动作 |
pass_file | html 时必填 | 仅文件名,如 land.html |
pass_url | redirect 时必填 | http/https 地址,或以 / 开头的站内路径 |
pass_path | path 时必填 | 以 / 开头的站内路径 |
fail_action | html / redirect / path / deny | 规则不通过时的动作 |
fail_file | html 时必填,缺省 safe.html | 仅文件名 |
fail_url | redirect 时必填 | 同 pass_url |
fail_path | path 时必填 | 同 pass_path |
deny_status | 403 / 404 / 204 / 410,缺省 404 | 仅 deny 使用 |
append_query | 0 / 1,缺省 1 | redirect 与 path 是否把当前地址栏 query 接到目标 |
fail_mode | html / allow,缺省 html | 通信失败或无法解析时:出安全页或出落地页 |
status | normal / disabled,缺省 normal | disabled 时判定接口返回 403 |
文件名、URL、路径约束:
- HTML 文件名:
^[A-Za-z0-9._-]+\.html$,最长 128;禁止..、/、\ - 跳转目标:最长 1024。
http/https且带 host,或以/开头的站内路径;禁止//evil.com、..、反斜杠 - 站内路径:最长 1024,必须以
/开头;禁止..、//、http、反斜杠、空白。可带 query(?后部分)
通过 / 拦截动作与目标在控制台保存后立即生效。密钥、场景 ID、fail_mode、包内默认 HTML 文件名写在脚本常量里,改这些需重新下载并覆盖脚本。
创建或轮换后可随时下载 PHP 包、Cloudflare Worker 与 Cloudflare Pages(Peek 打进 ZIP,可反复下同一把)。正式密钥只在轮换时更换;轮换或删除场景后旧钥立即失效,须重新下载并覆盖已部署脚本。
判定请求
官方脚本对平台发起:
POST /v1/decision
Authorization: Bearer <场景密钥>
Content-Type: application/json
Accept: application/json包内超时为 2500 ms。请求体:
| 字段 | 必填 | 约束 | 脚本怎么采 |
|---|---|---|---|
ip | 是 | 合法 IPv4 / IPv6 | CF-Connecting-IP → X-Real-IP → X-Forwarded-For 左一 → REMOTE_ADDR |
ua | 是 | 非空,最长 1024 | User-Agent |
referer | 否 | 最长 2048 | Referer |
language | 否 | 最长 256 | Accept-Language |
url | 是 | 最长 4096,须含 scheme 与 host | 当前完整 URL(含 query) |
scene_id | 是 | 正整数,且必须等于该密钥所属场景 | 下载时写入脚本常量 |
{
"ip": "203.0.113.10",
"ua": "Mozilla/5.0 ...",
"referer": "https://example.com/",
"language": "zh-CN,zh;q=0.9",
"url": "https://yoursite.com/",
"scene_id": 12
}scene_id 与密钥不匹配、场景停用时,接口返回 403。国家、ASN、代理等画像由平台根据 ip 等字段计算,脚本不在客户侧查第三方 IP 库。
判定响应
成功时 HTTP 200,正文:
{
"code": 200,
"msg": "SUCCESS",
"data": { "action": "allow" }
}data 随 action 带不同字段:
action | data 其它字段 | 脚本行为 |
|---|---|---|
allow | (无) | 出落地页。PHP / Cloudflare 使用包内 ALLOW_HTML_FILE(缺省 land.html) |
html | page:landing(通过)或 safe(拦截);file:HTML 文件名 | 出该文件 |
redirect | url;append_query(布尔) | 302 到 http/https 或站内路径 |
path | path;append_query(布尔) | 打开本站路径,地址栏不变 |
deny | status:403 / 404 / 204 / 410 | 只回该 HTTP 状态码,无正文 |
code 不是 200、传输失败或 JSON 无法解析时,走场景的 fail_mode(html 出安全页,allow 出落地页)。脚本响应带 Cache-Control: no-store。
公开判定常见失败(官方脚本一律走故障兜底,不向访客展示这些码):
| HTTP | 含义 |
|---|---|
| 401 | 密钥缺失或无效 |
| 403 | 未开通、场景停用、scene_id 不匹配,或账号不可用 |
| 400 | 请求字段不合法,或规则模板无效 |
| 429 | 当日次数用尽 |
| 503 | 平台暂不可用 |
PHP 与 Cloudflare
同一 action 对齐,实现随运行环境不同:
action | PHP(PHP 8.3) | Cloudflare |
|---|---|---|
html / allow | 读与 index.php 同目录的文件 | 无本地磁盘,对当前请求同源 GET 该文件名 |
path | 在网站文档根内 include;realpath 必须落在文档根内 | 对本站同源路径 fetch 后返回正文 |
redirect | 均为 302;append_query 缺省开 | 同左 |
deny | 对应 HTTP 状态码 | 同左 |
path 必须以 / 开头;禁止 ..、//、http、反斜杠。redirect 禁止 //evil.com。
控制台
- 开通后打开「边缘对接」
- 按上一节配置场景
- 下载官方 PHP 包、Cloudflare Worker 或 Cloudflare Pages
- 「判定记录」查看成功与失败,可按场景 / 通过 / 动作 / IP 筛选
页头显示今日已用 / 剩余,按套餐计算每日判定次数。
PHP 包
网站使用 PHP 8.3,并能出站 HTTPS 访问平台接口。包内脚本不会检查 PHP 版本号。官方 PHP 始终一包({name}-php.zip)。把文件放到站点目录,未命中真实文件的请求进 index.php。
- 下载官方 PHP 包并解压
- 放到网站目录(
index.php与页面文件在同一目录) - 按包内
.htaccess或nginx.conf.example配好伪静态(未命中真实文件的请求进index.php)。站点根/必须进index.php;若同目录已有index.html,访问/可能直接出静态首页、绕过判定 - 把占位页换成真实 HTML,文件名与控制台配置一致
包内:index.php(已写入 https 判定口、密钥与场景常量)、按场景文件名生成的占位页、README.txt、.htaccess、nginx.conf.example。命中真实文件(含带后缀的静态资源)的请求不进判定。落地页应由脚本输出,不要靠直接打开 /land.html 走规则。
Cloudflare Worker
站点源站已接入 Cloudflare、要绑 Worker 路由时,下载 {name}-cf-worker.zip。与 Pages 同一运行时,采集与动作相同:优先 CF-Connecting-IP,再带 UA、Referer、Accept-Language 与完整 URL,以 Bearer 调用判定接口。无 Node fs。html / path 从同源取文件。带后缀的静态文件直出,不走判定。
包内:
worker.jswrangler.toml.exampleREADME.txt- 按场景文件名生成的占位 HTML
不含 functions/ 与 _routes.json。不要与 Pages 中间件挂在同一路由上。
- 在控制台下载 Cloudflare Worker
- 把
land.html/safe.html(或场景里配置的文件名)放到源站同源可 GET 的位置 - 按 README 将
wrangler.toml.example改成wrangler.toml(填账号与路由) - 用 wrangler 部署,并把 Worker 绑到站点路由
html 动作从同源拉取文件(fetch(new URL('/' + file, request.url))),请保证这些文件在源站可访问。
Cloudflare Pages
站点在 Cloudflare Pages 上时,下载 {name}-cf-pages.zip。用包内 functions/_middleware.js(Pages Functions,与 Worker 同一运行时)。官方写法是全站中间件,拦站点根路径,与只挂某个子路径(例如 /go)的测法不同。不要与 Worker 挂在同一路由上。
包内:
functions/_middleware.js_routes.json(Pages 必须带上)README.txt- 按场景文件名生成的占位 HTML
- 把
functions/_middleware.js放到 Pages 项目的functions/目录 - 把包内
_routes.json放到 Pages 项目根(与functions同级)。若静态输出在public/(Astro / Vite 等),放到public/_routes.json,保证发布产物根目录带上该文件。Pages 必须带_routes.json - 把
land.html/safe.html(或场景文件名)放到站点根目录,与functions同级。不要放进与 Functions 同名的子目录(例如不要functions/go配静态/go/*.html),否则 Pages 会自动排除 Functions,中间件不会执行 - 项目里如果已经有
functions/_middleware.js(语言跳转、地区拦截等),不要整文件覆盖官方中间件;合并逻辑,或把判定挂到单独子路径,并仍保留_routes.json的include /* - 按 Pages 正常发布
Pages 没有本地磁盘。html / path 同源 GET:优先走 Pages 的 ASSETS;否则同源 fetch,并带内部头避免再次进入判定。
计次
仅公开判定成功计入当日次数。额度在平台统计。额度用尽或平台暂不可用时走故障兜底。
常见卡点
| 现象 | 可检查 |
|---|---|
| 看不到「边缘对接」 | 是否已开通;当前是否管理员 |
| 需要换钥或怀疑泄露 | 点轮换,再下载覆盖已部署脚本 |
| 上传后一直出安全页 | 规则是否符合预期;占位页是否已换成真实页;文件名是否一致 |
访问站点根 / 不出判定、一直静态首页 | 伪静态是否进 index.php;同目录 index.html 是否抢了首页 |
| Worker / Pages 一直出安全页或 html 未出页 | 同源文件能否 GET;路由是否打到脚本;Pages 是否把 html 放在站点根目录,且带上 _routes.json |
| Pages 中间件完全不执行 | 发布产物根是否有 _routes.json(include /*);落地 HTML 是否与 Functions 同路径前缀导致自动排除;已有根 _middleware 是否整文件覆盖了官方文件 |
| path 未出页 | PHP:路径是否在文档根内、伪静态是否进 index.php;Cloudflare:同源路径是否可 GET |
| 平台不可用时仍出落地页 | 故障兜底是否设成了放行(有风险) |