Cloudflare Workers加载图片如https://wsrv.nl/?url=

person 元章 event 2026-02-23 local_offer 代码 chat 评论
代码展示
"use strict";
(() => {
  // node_modules/reflare/dist/src/database/workers-kv.js
  var WorkersKV = class {
    namespace;
    constructor(namespace) {
      this.namespace = namespace;
    }
    get = async (key) => {
      const value = await this.namespace.get(key, {
        type: "json",
        cacheTtl: 60
      });
      return value;
    };
    put = async (key, value) => {
      await this.namespace.put(key, JSON.stringify(value));
    };
    delete = async (key) => {
      await this.namespace.delete(key);
    };
  };

  // node_modules/reflare/dist/src/middleware.js
  var usePipeline = (...initMiddlewares) => {
    const stack = [...initMiddlewares];
    const push = (...middlewares) => {
      stack.push(...middlewares);
    };
    const execute = async (context) => {
      const runner = async (prevIndex, index) => {
        if (index === prevIndex) {
          throw new Error("next() called multiple times");
        }
        if (index >= stack.length) {
          return;
        }
        const middleware = stack[index];
        const next = async () => runner(index, index + 1);
        await middleware(context, next);
      };
      await runner(-1, 0);
    };
    return {
      push,
      execute
    };
  };

  // node_modules/reflare/dist/src/middlewares/cors.js
  var useCORS = async (context, next) => {
    await next();
    const { request, response, route } = context;
    const corsOptions = route.cors;
    if (corsOptions === void 0) {
      return;
    }
    const { origin, methods, exposedHeaders, allowedHeaders, credentials, maxAge } = corsOptions;
    const requestOrigin = request.headers.get("origin");
    if (requestOrigin === null || origin === false) {
      return;
    }
    const corsHeaders = new Headers(response.headers);
    if (origin === true) {
      corsHeaders.set("Access-Control-Allow-Origin", requestOrigin);
    } else if (Array.isArray(origin)) {
      if (origin.includes(requestOrigin)) {
        corsHeaders.set("Access-Control-Allow-Origin", requestOrigin);
      }
    } else if (origin === "*") {
      corsHeaders.set("Access-Control-Allow-Origin", "*");
    }
    if (Array.isArray(methods)) {
      corsHeaders.set("Access-Control-Allow-Methods", methods.join(","));
    } else if (methods === "*") {
      corsHeaders.set("Access-Control-Allow-Methods", "*");
    } else {
      const requestMethod = request.headers.get("Access-Control-Request-Method");
      if (requestMethod !== null) {
        corsHeaders.set("Access-Control-Allow-Methods", requestMethod);
      }
    }
    if (Array.isArray(exposedHeaders)) {
      corsHeaders.set("Access-Control-Expose-Headers", exposedHeaders.join(","));
    } else if (exposedHeaders === "*") {
      corsHeaders.set("Access-Control-Expose-Headers", "*");
    }
    if (Array.isArray(allowedHeaders)) {
      corsHeaders.set("Access-Control-Allow-Headers", allowedHeaders.join(","));
    } else if (allowedHeaders === "*") {
      corsHeaders.set("Access-Control-Allow-Headers", "*");
    } else {
      const requestHeaders = request.headers.get("Access-Control-Request-Headers");
      if (requestHeaders !== null) {
        corsHeaders.set("Access-Control-Allow-Headers", requestHeaders);
      }
    }
    if (credentials === true) {
      corsHeaders.set("Access-Control-Allow-Credentials", "true");
    }
    if (maxAge !== void 0 && Number.isInteger(maxAge)) {
      corsHeaders.set("Access-Control-Max-Age", maxAge.toString());
    }
    context.response = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: corsHeaders
    });
  };

  // node_modules/reflare/dist/src/middlewares/firewall.js
  var fields = /* @__PURE__ */ new Set([
    "country",
    "continent",
    "asn",
    "ip",
    "hostname",
    "user-agent"
  ]);
  var operators = /* @__PURE__ */ new Set([
    "equal",
    "not equal",
    "greater",
    "less",
    "in",
    "not in",
    "contain",
    "not contain",
    "match",
    "not match"
  ]);
  var validateFirewall = ({ field, operator, value }) => {
    if (field === void 0 || operator === void 0 || value === void 0) {
      throw new Error("Invalid 'firewall' field in the option object");
    }
    if (fields.has(field) === false) {
      throw new Error("Invalid 'firewall' field in the option object");
    }
    if (operators.has(operator) === false) {
      throw new Error("Invalid 'firewall' field in the option object");
    }
  };
  var getFieldParam = (request, field) => {
    const cfProperties = request.cf;
    switch (field) {
      case "asn":
        return cfProperties?.asn;
      case "continent":
        return cfProperties?.continent;
      case "country":
        return cfProperties?.country;
      case "hostname":
        return request.headers.get("host") || "";
      case "ip":
        return request.headers.get("cf-connecting-ip") || "";
      case "user-agent":
        return request.headers.get("user-agent") || "";
      default:
        return void 0;
    }
  };
  var matchOperator = (fieldParam, value) => {
    if (!(value instanceof RegExp)) {
      throw new Error("You must use 'new RegExp('...')' for 'value' in firewall configuration to use 'match' or 'not match' operator");
    }
    return value.test(fieldParam.toString());
  };
  var notMatchOperator = (fieldParam, value) => !matchOperator(fieldParam, value);
  var equalOperator = (fieldParam, value) => fieldParam === value;
  var notEqualOperator = (fieldParam, value) => fieldParam !== value;
  var greaterOperator = (fieldParam, value) => {
    if (typeof fieldParam !== "number" || typeof value !== "number") {
      throw new Error("You must use number for 'value' in firewall configuration to use 'greater' or 'less' operator");
    }
    return fieldParam > value;
  };
  var lessOperator = (fieldParam, value) => {
    if (typeof fieldParam !== "number" || typeof value !== "number") {
      throw new Error("You must use number for 'value' in firewall configuration to use 'greater' or 'less' operator");
    }
    return fieldParam < value;
  };
  var containOperator = (fieldParam, value) => {
    if (typeof fieldParam !== "string" || typeof value !== "string") {
      throw new Error("You must use string for 'value' in firewall configuration to use 'contain' or 'not contain' operator");
    }
    return fieldParam.includes(value);
  };
  var notContainOperator = (fieldParam, value) => !containOperator(fieldParam, value);
  var inOperator = (fieldParam, value) => {
    if (!Array.isArray(value)) {
      throw new Error("You must use an Array for 'value' in firewall configuration to use 'in' or 'not in' operator");
    }
    return value.some((item) => item === fieldParam);
  };
  var notInOperator = (fieldParam, value) => !inOperator(fieldParam, value);
  var operatorsMap = {
    match: matchOperator,
    contain: containOperator,
    equal: equalOperator,
    in: inOperator,
    greater: greaterOperator,
    less: lessOperator,
    "not match": notMatchOperator,
    "not contain": notContainOperator,
    "not equal": notEqualOperator,
    "not in": notInOperator
  };
  var useFirewall = async (context, next) => {
    const { request, route } = context;
    if (route.firewall === void 0) {
      await next();
      return;
    }
    route.firewall.forEach(validateFirewall);
    for (const { field, operator, value } of route.firewall) {
      const fieldParam = getFieldParam(request, field);
      if (fieldParam !== void 0 && operatorsMap[operator](fieldParam, value)) {
        throw new Error("You don't have permission to access this service.");
      }
    }
    await next();
  };

  // node_modules/reflare/dist/src/middlewares/headers.js
  var setForwardedHeaders = (headers) => {
    headers.set("X-Forwarded-Proto", "https");
    const host = headers.get("Host");
    if (host !== null) {
      headers.set("X-Forwarded-Host", host);
    }
    const ip = headers.get("cf-connecting-ip");
    const forwardedForHeader = headers.get("X-Forwarded-For");
    if (ip !== null && forwardedForHeader === null) {
      headers.set("X-Forwarded-For", ip);
    }
  };
  var useHeaders = async (context, next) => {
    const { request, route } = context;
    const requestHeaders = new Headers(request.headers);
    setForwardedHeaders(requestHeaders);
    if (route.headers === void 0) {
      context.request = new Request(request.url, {
        body: request.body,
        method: request.method,
        headers: requestHeaders
      });
      await next();
      return;
    }
    if (route.headers.request !== void 0) {
      for (const [key, value] of Object.entries(route.headers.request)) {
        if (value.length === 0) {
          requestHeaders.delete(key);
        } else {
          requestHeaders.set(key, value);
        }
      }
    }
    context.request = new Request(request.url, {
      body: request.body,
      method: request.method,
      headers: requestHeaders
    });
    await next();
    const { response } = context;
    const responseHeaders = new Headers(response.headers);
    if (route.headers.response !== void 0) {
      for (const [key, value] of Object.entries(route.headers.response)) {
        if (value.length === 0) {
          responseHeaders.delete(key);
        } else {
          responseHeaders.set(key, value);
        }
      }
    }
    context.response = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: responseHeaders
    });
  };

  // node_modules/reflare/dist/src/utils.js
  var getHostname = (request) => {
    const url = new URL(request.url);
    return url.host;
  };
  var castToIterable = (value) => Array.isArray(value) ? value : [value];

  // node_modules/reflare/dist/src/middlewares/load-balancing.js
  var validateUpstream = (upstream) => {
    if (upstream.domain === void 0) {
      throw new Error("Invalid 'upstream' field in the option object");
    }
  };
  var ipHashHandler = (upstream, request) => {
    const ipString = request.headers.get("cf-connecting-ip") || "0.0.0.0";
    const userIP = ipString.split(".").map((octet, index, array) => parseInt(octet, 10) * 256 ** (array.length - index - 1)).reduce((accumulator, current) => accumulator + current);
    return upstream[userIP % upstream.length];
  };
  var randomHandler = (upstream) => {
    const weights = upstream.map((option) => option.weight === void 0 ? 1 : option.weight);
    const totalWeight = weights.reduce((acc, num, index) => {
      const sum = acc + num;
      weights[index] = sum;
      return sum;
    });
    if (totalWeight === 0) {
      throw new Error("Total weights should be greater than 0.");
    }
    const random = Math.random() * totalWeight;
    for (const index of weights.keys()) {
      if (weights[index] >= random) {
        return upstream[index];
      }
    }
    return upstream[Math.floor(Math.random() * upstream.length)];
  };
  var handlersMap = {
    random: randomHandler,
    "ip-hash": ipHashHandler
  };
  var useLoadBalancing = async (context, next) => {
    const { request, route } = context;
    const { upstream, loadBalancing } = route;
    if (upstream === void 0) {
      throw new Error("The required 'upstream' field in the option object is missing");
    }
    const upstreamIterable = castToIterable(upstream);
    upstreamIterable.forEach(validateUpstream);
    if (loadBalancing === void 0) {
      context.upstream = randomHandler(upstreamIterable, request);
      await next();
      return;
    }
    const policy = loadBalancing.policy || "random";
    const policyHandler = handlersMap[policy];
    context.upstream = policyHandler(upstreamIterable, request);
    await next();
  };

  // node_modules/reflare/dist/src/middlewares/upstream.js
  var rewriteURL = (url, upstream) => {
    const cloneURL = new URL(url);
    const { domain, port, protocol } = upstream;
    cloneURL.hostname = domain;
    if (protocol !== void 0) {
      cloneURL.protocol = `${protocol}:`;
    }
    if (port === void 0) {
      cloneURL.port = "";
    } else {
      cloneURL.port = port.toString();
    }
    return cloneURL.href;
  };
  var useUpstream = async (context, next) => {
    const { request, upstream } = context;
    if (upstream === null) {
      await next();
      return;
    }
    const url = rewriteURL(request.url, upstream);
    context.request = new Request(url, context.request);
    if (upstream.onRequest) {
      const onRequest = castToIterable(upstream.onRequest);
      for await (const fn of onRequest) {
        context.request = await fn(context.request, url);
      }
    }
    context.response = (await fetch(context.request)).clone();
    if (upstream.onResponse) {
      const onResponse = castToIterable(upstream.onResponse);
      for await (const fn of onResponse) {
        context.response = await fn(context.response, url);
      }
    }
    await next();
  };

  // node_modules/reflare/dist/src/index.js
  var filter = (request, routeList) => {
    const url = new URL(request.url);
    for (const route of routeList) {
      if (route.domain) {
        const match = castToIterable(route.domain).some((domain) => {
          const re = RegExp(`^${domain.replace(/(\/?)\*/g, "($1.*)?").replace(/\/$/, "").replace(/:(\w+)(\?)?(\.)?/g, "$2(?<$1>[^/]+)$2$3").replace(/\.(?=[\w(])/, "\\.").replace(/\)\.\?\(([^[]+)\[\^/g, "?)\\.?($1(?<=\\.)[^\\.")}/*$`);
          return url.hostname.match(re);
        });
        if (!match) {
          continue;
        }
      }
      if (route.methods === void 0 || route.methods.includes(request.method)) {
        const match = castToIterable(route.path).some((path) => {
          const re = RegExp(`^${path.replace(/(\/?)\*/g, "($1.*)?").replace(/\/$/, "").replace(/:(\w+)(\?)?(\.)?/g, "$2(?<$1>[^/]+)$2$3").replace(/\.(?=[\w(])/, "\\.").replace(/\)\.\?\(([^[]+)\[\^/g, "?)\\.?($1(?<=\\.)[^\\.")}/*$`);
          return url.pathname.match(re);
        });
        if (match) {
          return route;
        }
      }
    }
    return void 0;
  };
  var defaultOptions = {
    provider: "static",
    routeList: []
  };
  var useReflare = async (options = defaultOptions) => {
    const pipeline = usePipeline(useFirewall, useLoadBalancing, useHeaders, useCORS, useUpstream);
    const routeList = [];
    if (options.provider === "static") {
      for (const route of options.routeList) {
        routeList.push(route);
      }
    }
    if (options.provider === "kv") {
      const database = new WorkersKV(options.namespace);
      const routeListKV = await database.get("route-list") || [];
      for (const routeKV of routeListKV) {
        routeList.push(routeKV);
      }
    }
    const handle = async (request) => {
      const route = filter(request, routeList);
      if (route === void 0) {
        return new Response("Failed to find a route that matches the path and method of the current request", {
          status: 500
        });
      }
      const context = {
        request: new Request(request),
        route,
        hostname: getHostname(request),
        response: new Response("Unhandled response"),
        upstream: null
      };
      try {
        await pipeline.execute(context);
      } catch (error) {
        if (error instanceof Error) {
          context.response = new Response(error.message, {
            status: 500
          });
        }
      }
      return context.response;
    };
    const unshift = (route) => {
      routeList.unshift(route);
    };
    const push = (route) => {
      routeList.push(route);
    };
    return {
      handle,
      unshift,
      push
    };
  };
  var src_default = useReflare;

  // src/main.ts
  var handleRequest = async (request) => {
    const u = new URL(request.url);
    const url = u.searchParams.get("url");
    if (!url) {
      return new Response("Missing url", {
        status: 400,
        statusText: "Missing url"
      });
    }
    const reflare = await src_default();
    const route = {
      path: new URL(url).pathname,
      upstream: {
        domain: new URL(url).host,
        protocol: new URL(url).protocol
      }
    };
    console.log(route);
    reflare.push(route);
    return reflare.handle(new Request(url, request));
  };
  addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event.request));
  });
})();
//# sourceMappingURL=main.js.map

copyright 版权声明

相关文章

评论