侧边栏壁纸
博主头像
いちごみるく

行动起来,活在当下

  • 累计撰写 70 篇文章
  • 累计创建 48 个标签
  • 累计收到 55 条评论

目 录CONTENT

文章目录

历史实验:Cloudflare Workers 转发 Bilibili 港澳台番剧 API

历史实验。 本文记录 2023 年用 Cloudflare Workers 转发 Bilibili API 的结构。地区许可、登录授权、接口和 CDN 出口会变化;截图和地址信息不代表当前番剧播放可用,不能将此实验当作可靠的地区服务。

一、当时的思路与实际边界

浏览器脚本把指定 API 请求送到自定义 Workers 域名,Worker 再访问 api.bilibili.com。这改变了 API 的请求路径,未必改变视频媒体出口,也不能创造帐号本来没有的会员或内容权限。

选择某个 CDN 入口 IP,不能据此指定台湾回源出口。Cloudflare IP 说明描述的是 Anycast:同一个 IP 可以在多个机房宣告。入口位置、Worker 执行位置、回源出口和平台使用的 IP 地理数据库是不同信息。访问 /cdn-cgi/trace 得到某个机房,也不能证明另一个请求使用同一地区出口。

162.158.243.0/24 是当时实验用到的地址段,不代表整个网段都可用于当前服务或固定从台湾回源。官方 DNS/CNAME 接入方式更适合长期维护,不应靠固定第三方 IP 清单判断播放权限。

二、修正普通 HTTP 转发中的代码错误

HTTP 转发需要保留请求方法、请求头和请求体;只传 method 与 headers 会漏掉 POST 等请求的数据。读取可选请求头时也应处理缺失值,避免直接调用 toUpperCase() 报错。下面的示例仅允许两个历史 PGC 路径,用于说明普通 HTTP 转发,不包含当前 Bilibili API 或 gRPC 播放的完整适配。

const allowedPaths = new Set([
  "/pgc/player/web/playurl",
  "/pgc/view/web/season"
]);
const allowedOrigin = "https://www.bilibili.com";

export default {
  async fetch(request) {
    const target = new URL(request.url);
    if (!allowedPaths.has(target.pathname)) {
      return new Response("Not found", { status: 404 });
    }
    const origin = request.headers.get("Origin");
    if (origin && origin !== allowedOrigin) {
      return new Response("Origin not allowed", { status: 403 });
    }
    if (request.method === "OPTIONS") {
      return new Response(null, {
        status: 204,
        headers: {
          "Access-Control-Allow-Origin": allowedOrigin,
          "Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
          "Access-Control-Allow-Headers": "Content-Type, Authorization",
          "Access-Control-Allow-Credentials": "true",
          "Vary": "Origin"
        }
      });
    }
    if (!["GET", "HEAD", "POST"].includes(request.method)) {
      return new Response("Method not allowed", { status: 405 });
    }

    target.protocol = "https:";
    target.hostname = "api.bilibili.com";
    target.port = "";
    const headers = new Headers(request.headers);
    headers.delete("Host");
    const forwarded = new Request(target.toString(), request);
    const upstream = await fetch(new Request(forwarded, {
      headers,
      redirect: "manual",
      cache: "no-store"
    }));
    const output = new Response(upstream.body, upstream);
    output.headers.set("Cache-Control", "private, no-store");
    output.headers.append("Vary", "Origin");
    if (origin === allowedOrigin) {
      output.headers.set("Access-Control-Allow-Origin", allowedOrigin);
      output.headers.set("Access-Control-Allow-Credentials", "true");
    }
    return output;
  }
};

new Request(target, request) 保留请求方法和请求体;重定向使用 manual,避免 Worker 自动把 Cookie/Authorization 送到意外的新域名。CORS 白名单只控制浏览器读取,不是身份认证;公开服务仍需另外设计限流、授权和日志脱敏。不能缓存携带账号上下文的 API 应答,也不应收集或公开账号令牌。Workers Request 文档说明了克隆与重定向行为。

普通 fetch 示例不等于完整 gRPC 代理。2026 年 Cloudflare 宣布了 gRPC-web 转换等新能力的 private beta;它们有自己的配置和开放范围,不能从普通 fetch 转发推断所有双向流与 trailers 都得到支持。官方公告是核查新能力的入口。

三、历史界面与绑定

2023 年 Workers 编辑界面

2023 年绑定域名界面

产品名称是 Workers。自定义域名与 Route 是不同入口,按当前控制台设置并验证 DNS/TLS;不能概括为所有地区都无法使用 workers.dev。在同一个域名随意混合三家 CDN 的地址,还需要各家都配置该域名和正确证书,不能只增加 A 记录就保证兼容。

四、如何判断这个实验是否仍适合使用

分开验证 API 的 JSON/业务错误、登录状态、具体内容授权、媒体播放与出口,不要只看 HTTP 200、节点地理标签或一个能播放的样本。公共转发服务与 IP 清单还需核对维护状态,不应直接作为长期固定入口。

与之相关的CloudFront、Gcore和iOS 请求改写也应按各自历史范围阅读。

0

评论区