cloudflare worker代理,可代理github、AI接口、下载

这也不算推广吧,只有一个脚本的代码,没有仓库,只是分享脚本。 一个简单的cloudflare worker代理,完全透传,不修改任何参数、header,但是worker出去的请求会带有cf headers,无法避免。 支持,单不限于 API代理 各AI服务接口流式输出 下载 github克隆、raw...
cloudflare worker代理,可代理github、AI接口、下载
cloudflare worker代理,可代理github、AI接口、下载

这也不算推广吧,只有一个脚本的代码,没有仓库,只是分享脚本。

一个简单的cloudflare worker代理,完全透传,不修改任何参数、header,但是worker出去的请求会带有cf headers,无法避免。

支持,单不限于

  • API代理
  • 各AI服务接口流式输出
  • 下载
  • github克隆、raw.github访问

只有一个js脚本,打开cloudflare计算,点击创建应用程序,从hello world开始,点击部署后将代码修改为脚本内容。

支持环境变量设置黑白名单、apikey

  • ALLOWED_ORIGINS 逗号分隔的允许来源,如 https://a.com,https://b.com
  • PROXY_KEY 访问密钥字符串
  • BLOCKED_HOSTS 逗号分隔的屏蔽域名,追加到默认列表之后

使用方式 https://xx.workers.dev/<url>,建议给worker添加自定义域,访问更通畅。设置PROXY_KEY之后可以添加x-proxy-key header来访问

image

代码如下:

/**
 * Cloudflare Worker — 透明代理
 *
 * 用法:https://<your-worker>.workers.dev/<目标URL>
 * 示例:https://proxy.example.workers.dev/https://api.openai.com/v1/chat/completions
 *
 * 支持:HTTP / HTTPS / SSE 流式 / 文件下载 / OpenAI streaming
 */

// ─── 默认配置(可被环境变量覆盖)────────────────────────────────────────────────

const DEFAULTS = {
  // 允许访问的来源域,逗号分隔;留空则允许所有
  // 环境变量:ALLOWED_ORIGINS=https://example.com,https://app.example.com
  allowedOrigins: [],

  // 密钥鉴权;留空则关闭
  // 环境变量:PROXY_KEY=your-secret-key
  proxyKey: "",

  // 屏蔽的目标域,逗号分隔
  // 环境变量:BLOCKED_HOSTS=169.254.169.254,metadata.google.internal,10.0.0.0/8
  // 注:代码只做精确域名匹配,CIDR 写在这里不会生效,仅作标注提示用
  blockedHosts: [
    "169.254.169.254", // AWS / Azure metadata
    "metadata.google.internal", // GCP metadata
  ],
};

// 转发时固定去掉的 hop-by-hop 头(不受环境变量影响)
const HOP_BY_HOP = new Set([
  "connection",
  "keep-alive",
  "proxy-authenticate",
  "proxy-authorization",
  "te",
  "trailers",
  "transfer-encoding",
  "upgrade",
  "host",
  "cf-connecting-ip",
  "cf-ipcountry",
  "cf-ray",
  "cf-visitor",
  "x-forwarded-for",
  "x-real-ip",
  "x-proxy-key",
]);

/**
 * 从环境变量和默认值构建运行时配置。
 * 每次请求调用一次,开销极小。
 *
 * 支持的环境变量(均在 CF Workers 控制台 Settings → Variables 中配置):
 *   ALLOWED_ORIGINS  逗号分隔的允许来源,如 https://a.com,https://b.com
 *   PROXY_KEY        访问密钥字符串
 *   BLOCKED_HOSTS    逗号分隔的屏蔽域名,追加到默认列表之后
 */
function buildConfig(env) {
  // 解析 ALLOWED_ORIGINS
  const allowedOrigins = env.ALLOWED_ORIGINS
    ? env.ALLOWED_ORIGINS.split(",")
        .map((s) => s.trim())
        .filter(Boolean)
    : DEFAULTS.allowedOrigins;

  // 解析 PROXY_KEY
  const proxyKey = env.PROXY_KEY?.trim() ?? DEFAULTS.proxyKey;

  // 解析 BLOCKED_HOSTS:环境变量里的条目追加到默认列表
  const extraBlocked = env.BLOCKED_HOSTS
    ? env.BLOCKED_HOSTS.split(",")
        .map((s) => s.trim())
        .filter(Boolean)
    : [];
  const blockedHosts = [...DEFAULTS.blockedHosts, ...extraBlocked];

  return { allowedOrigins, proxyKey, blockedHosts };
}

// ─── 入口 ──────────────────────────────────────────────────────────────────────

export default {
  async fetch(request, env) {
    const config = buildConfig(env);

    // preflight
    if (request.method === "OPTIONS") {
      return corsPreflightResponse(request);
    }

    // 鉴权
    if (config.proxyKey) {
      const key = request.headers.get("x-proxy-key") ?? "";
      if (key !== config.proxyKey) {
        return errorResponse(403, "Forbidden: invalid proxy key");
      }
    }

    // 解析目标 URL
    const url = new URL(request.url);
    // path 形如 /https://github.com/...  或  /http://...
    const rawTarget = url.pathname.slice(1) + url.search; // 去掉首个 /
    if (!rawTarget) {
      return new Response(HELP_PAGE, {
        headers: { "content-type": "text/html;charset=utf-8" },
      });
    }

    let targetUrl;
    try {
      targetUrl = new URL(decodeURIComponent(rawTarget));
    } catch {
      return errorResponse(400, `Bad target URL: ${rawTarget}`);
    }

    if (!["http:", "https:"].includes(targetUrl.protocol)) {
      return errorResponse(400, "Only http/https targets are supported");
    }

    // 屏蔽内网 / 危险主机
    const targetHost = targetUrl.hostname.toLowerCase();
    for (const blocked of config.blockedHosts) {
      if (targetHost === blocked || targetHost.endsWith("." + blocked)) {
        return errorResponse(403, `Blocked host: ${targetHost}`);
      }
    }

    // 构造转发请求头
    const forwardHeaders = new Headers();
    for (const [k, v] of request.headers.entries()) {
      if (!HOP_BY_HOP.has(k.toLowerCase())) {
        forwardHeaders.set(k, v);
      }
    }
    forwardHeaders.set("host", targetUrl.host);

    // 处理 body(GET/HEAD 不带 body)
    const hasBody = !["GET", "HEAD"].includes(request.method);
    const body = hasBody ? request.body : undefined;

    // 发起请求(CF Worker 的 fetch 天然支持流式响应 + HTTP/2)
    let targetResponse;
    try {
      targetResponse = await fetch(targetUrl.toString(), {
        method: request.method,
        headers: forwardHeaders,
        body,
        // redirect: "follow" 是默认值,如需暴露重定向给客户端可改为 "manual"
        redirect: "follow",
      });
    } catch (err) {
      return errorResponse(502, `Upstream fetch failed: ${err.message}`);
    }

    // 构造响应头(去掉 hop-by-hop,加上 CORS)
    const respHeaders = new Headers();
    for (const [k, v] of targetResponse.headers.entries()) {
      if (!HOP_BY_HOP.has(k.toLowerCase())) {
        respHeaders.set(k, v);
      }
    }

    // 注入 CORS
    addCorsHeaders(respHeaders, request, config);

    // 关键:直接透传 body(ReadableStream),零拷贝,支持下载/SSE/流式 LLM
    return new Response(targetResponse.body, {
      status: targetResponse.status,
      statusText: targetResponse.statusText,
      headers: respHeaders,
    });
  },
};

// ─── 工具函数 ──────────────────────────────────────────────────────────────────

function addCorsHeaders(headers, request, config) {
  const origin = request.headers.get("origin") ?? "*";
  const allowed =
    config.allowedOrigins.length === 0 ||
    config.allowedOrigins.includes(origin);

  headers.set("access-control-allow-origin", allowed ? origin : "null");
  headers.set("access-control-allow-credentials", "true");
  headers.set("access-control-expose-headers", "*");
}

function corsPreflightResponse(request) {
  const origin = request.headers.get("origin") ?? "*";
  return new Response(null, {
    status: 204,
    headers: {
      "access-control-allow-origin": origin,
      "access-control-allow-methods": "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS",
      "access-control-allow-headers":
        request.headers.get("access-control-request-headers") ??
        "content-type,authorization,x-proxy-key",
      "access-control-max-age": "86400",
    },
  });
}

function errorResponse(status, message) {
  return new Response(JSON.stringify({ error: message }), {
    status,
    headers: {
      "content-type": "application/json",
      "access-control-allow-origin": "*",
    },
  });
}

// ─── 帮助页(访问根路径时显示)──────────────────────────────────────────────────

const HELP_PAGE = `<!DOCTYPE html>
<html lang="zh">
<head><meta charset="utf-8"><title>Transparent Proxy</title>
<style>
  body{font-family:system-ui,sans-serif;max-width:640px;margin:60px auto;padding:0 20px;line-height:1.7}
  code{background:#f0f0f0;padding:2px 6px;border-radius:4px;font-size:.9em}
  pre{background:#f6f6f6;padding:16px;border-radius:8px;overflow-x:auto}
</style></head>
<body>
<h1>🔀 Transparent Proxy Worker</h1>
<p>将目标 URL 附加在路径后即可代理任意 HTTP/HTTPS 资源。</p>

<h2>用法</h2>
<pre><code>https://&lt;worker&gt;.workers.dev/&lt;目标URL&gt;</code></pre>

<h2>示例</h2>
<pre>
# 普通 GET
curl https://proxy.example.workers.dev/https://httpbin.org/get

# 代理 OpenAI 流式接口(SSE)
curl -N -X POST \\
  -H "Authorization: Bearer $OPENAI_KEY" \\
  -H "Content-Type: application/json" \\
  -d '{"model":"gpt-4o","stream":true,"messages":[{"role":"user","content":"hi"}]}' \\
  https://proxy.example.workers.dev/https://api.openai.com/v1/chat/completions

# 下载大文件
curl -L -o output.zip \\
  https://proxy.example.workers.dev/https://example.com/large-file.zip
</pre>

<h2>支持特性</h2>
<ul>
  <li>✅ HTTP / HTTPS 透明转发</li>
  <li>✅ SSE / 流式 LLM 响应</li>
  <li>✅ 大文件下载(零拷贝流式透传)</li>
  <li>✅ 自动注入 CORS 头</li>
  <li>✅ 可选密钥鉴权(X-Proxy-Key)</li>
</ul>
</body></html>`;

1 个帖子 - 1 位参与者

阅读完整话题

来源: linux.do查看原文