警告
根据 Cloudflare 协议 中,2.2.1 第 (j) use the Services to provide a virtual private network or other similar proxy services.
使用本文某些应用可能存在被 Cloudflare 封号的潜在风险,请自行斟酌使用风险。
前言
本文是一个合集,主要收集各种Cloudflare可以搭建的免费应用(主要是Worker和Pages),所以这篇文章也会持续更新。
这里我只会放上项目图片,链接以及代码,具体的操作方法请看这篇文章(简单来说就是新建Worker然后粘贴代码)
注:可通过右侧或底部目录快速查找和切换
正文
JS在线代理
'use strict'
/**
* static files (404.html, sw.js, conf.js)
*/
const ASSET_URL = 'https://etherdream.github.io/jsproxy'
const JS_VER = 10
const MAX_RETRY = 1
/** @type {RequestInit} */
const PREFLIGHT_INIT = {
status: 204,
headers: new Headers({
'access-control-allow-origin': '*',
'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',
'access-control-max-age': '1728000',
}),
}
/**
* @param {any} body
* @param {number} status
* @param {Object<string, string>} headers
*/
function makeRes(body, status = 200, headers = {}) {
headers['--ver'] = JS_VER
headers['access-control-allow-origin'] = '*'
return new Response(body, {status, headers})
}
/**
* @param {string} urlStr
*/
function newUrl(urlStr) {
try {
return new URL(urlStr)
} catch (err) {
return null
}
}
addEventListener('fetch', e => {
const ret = fetchHandler(e)
.catch(err => makeRes('cfworker error:\n' + err.stack, 502))
e.respondWith(ret)
})
/**
* @param {FetchEvent} e
*/
async function fetchHandler(e) {
const req = e.request
const urlStr = req.url
const urlObj = new URL(urlStr)
const path = urlObj.href.substr(urlObj.origin.length)
if (urlObj.protocol === 'http:') {
urlObj.protocol = 'https:'
return makeRes('', 301, {
'strict-transport-security': 'max-age=99999999; includeSubDomains; preload',
'location': urlObj.href,
})
}
if (path.startsWith('/http/')) {
return httpHandler(req, path.substr(6))
}
switch (path) {
case '/http':
return makeRes('请更新 cfworker 到最新版本!')
case '/ws':
return makeRes('not support', 400)
case '/works':
return makeRes('it works')
default:
// static files
return fetch(ASSET_URL + path)
}
}
/**
* @param {Request} req
* @param {string} pathname
*/
function httpHandler(req, pathname) {
const reqHdrRaw = req.headers
if (reqHdrRaw.has('x-jsproxy')) {
return Response.error()
}
// preflight
if (req.method === 'OPTIONS' &&
reqHdrRaw.has('access-control-request-headers')
) {
return new Response(null, PREFLIGHT_INIT)
}
let acehOld = false
let rawSvr = ''
let rawLen = ''
let rawEtag = ''
const reqHdrNew = new Headers(reqHdrRaw)
reqHdrNew.set('x-jsproxy', '1')
// 此处逻辑和 http-dec-req-hdr.lua 大致相同
// https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua
const refer = reqHdrNew.get('referer')
const query = refer.substr(refer.indexOf('?') + 1)
if (!query) {
return makeRes('missing params', 403)
}
const param = new URLSearchParams(query)
for (const [k, v] of Object.entries(param)) {
if (k.substr(0, 2) === '--') {
// 系统信息
switch (k.substr(2)) {
case 'aceh':
acehOld = true
break
case 'raw-info':
[rawSvr, rawLen, rawEtag] = v.split('|')
break
}
} else {
// 还原 HTTP 请求头
if (v) {
reqHdrNew.set(k, v)
} else {
reqHdrNew.delete(k)
}
}
}
if (!param.has('referer')) {
reqHdrNew.delete('referer')
}
// cfworker 会把路径中的 `//` 合并成 `/`
const urlStr = pathname.replace(/^(https?):\/+/, '$1://')
const urlObj = newUrl(urlStr)
if (!urlObj) {
return makeRes('invalid proxy url: ' + urlStr, 403)
}
/** @type {RequestInit} */
const reqInit = {
method: req.method,
headers: reqHdrNew,
redirect: 'manual',
}
if (req.method === 'POST') {
reqInit.body = req.body
}
return proxy(urlObj, reqInit, acehOld, rawLen, 0)
}
/**
*
* @param {URL} urlObj
* @param {RequestInit} reqInit
* @param {number} retryTimes
*/
async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
const res = await fetch(urlObj.href, reqInit)
const resHdrOld = res.headers
const resHdrNew = new Headers(resHdrOld)
let expose = '*'
for (const [k, v] of resHdrOld.entries()) {
if (k === 'access-control-allow-origin' ||
k === 'access-control-expose-headers' ||
k === 'location' ||
k === 'set-cookie'
) {
const x = '--' + k
resHdrNew.set(x, v)
if (acehOld) {
expose = expose + ',' + x
}
resHdrNew.delete(k)
}
else if (acehOld &&
k !== 'cache-control' &&
k !== 'content-language' &&
k !== 'content-type' &&
k !== 'expires' &&
k !== 'last-modified' &&
k !== 'pragma'
) {
expose = expose + ',' + k
}
}
if (acehOld) {
expose = expose + ',--s'
resHdrNew.set('--t', '1')
}
// verify
if (rawLen) {
const newLen = resHdrOld.get('content-length') || ''
const badLen = (rawLen !== newLen)
if (badLen) {
if (retryTimes < MAX_RETRY) {
urlObj = await parseYtVideoRedir(urlObj, newLen, res)
if (urlObj) {
return proxy(urlObj, reqInit, acehOld, rawLen, retryTimes + 1)
}
}
return makeRes(res.body, 400, {
'--error': `bad len: ${newLen}, except: ${rawLen}`,
'access-control-expose-headers': '--error',
})
}
if (retryTimes > 1) {
resHdrNew.set('--retry', retryTimes)
}
}
let status = res.status
resHdrNew.set('access-control-expose-headers', expose)
resHdrNew.set('access-control-allow-origin', '*')
resHdrNew.set('--s', status)
resHdrNew.set('--ver', JS_VER)
resHdrNew.delete('content-security-policy')
resHdrNew.delete('content-security-policy-report-only')
resHdrNew.delete('clear-site-data')
if (status === 301 ||
status === 302 ||
status === 303 ||
status === 307 ||
status === 308
) {
status = status + 10
}
return new Response(res.body, {
status,
headers: resHdrNew,
})
}
/**
* @param {URL} urlObj
*/
function isYtUrl(urlObj) {
return (
urlObj.host.endsWith('.googlevideo.com') &&
urlObj.pathname.startsWith('/videoplayback')
)
}
/**
* @param {URL} urlObj
* @param {number} newLen
* @param {Response} res
*/
async function parseYtVideoRedir(urlObj, newLen, res) {
if (newLen > 2000) {
return null
}
if (!isYtUrl(urlObj)) {
return null
}
try {
const data = await res.text()
urlObj = new URL(data)
} catch (err) {
return null
}
if (!isYtUrl(urlObj)) {
return null
}
return urlObj
}
Gemini中转API(openAI格式)
function __cf_cjs(esm) {
const cjs = 'default' in esm ? esm.default : {};
for (const [k, v] of Object.entries(esm)) {
if (k !== 'default') {
Object.defineProperty(cjs, k, {
enumerable: true,
value: v,
});
}
}
return cjs;
}
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// node_modules/wrangler/_virtual_unenv_global_polyfill-clear$immediate.js
globalThis.clearImmediate = clearImmediateFallback;
// node_modules/unenv/runtime/_internal/utils.mjs
function createNotImplementedError(name) {
return new Error(`[unenv] ${name} is not implemented yet!`);
}
__name(createNotImplementedError, "createNotImplementedError");
function notImplemented(name) {
const fn2 = /* @__PURE__ */ __name(() => {
throw createNotImplementedError(name);
}, "fn");
return Object.assign(fn2, { __unenv__: true });
}
__name(notImplemented, "notImplemented");
// node_modules/unenv/runtime/mock/noop.mjs
var noop_default = Object.assign(() => {
}, { __unenv__: true });
// node_modules/unenv/runtime/node/timers/internal/immediate.mjs
var Immediate = class {
_onImmediate;
_timeout;
constructor(callback, args) {
this._onImmediate = callback;
if ("setTimeout" in globalThis) {
this._timeout = setTimeout(callback, 0, ...args);
} else {
callback(...args);
}
}
ref() {
this._timeout?.ref();
return this;
}
unref() {
this._timeout?.unref();
return this;
}
hasRef() {
return this._timeout?.hasRef() ?? false;
}
[Symbol.dispose]() {
if ("clearTimeout" in globalThis) {
clearTimeout(this._timeout);
}
}
};
__name(Immediate, "Immediate");
// node_modules/unenv/runtime/node/timers/internal/set-immediate.mjs
function setImmediateFallbackPromises(value) {
return new Promise((res) => {
res(value);
});
}
__name(setImmediateFallbackPromises, "setImmediateFallbackPromises");
function setImmediateFallback(callback, ...args) {
return new Immediate(callback, args);
}
__name(setImmediateFallback, "setImmediateFallback");
setImmediateFallback.__promisify__ = setImmediateFallbackPromises;
function clearImmediateFallback(immediate) {
immediate?.[Symbol.dispose]();
}
__name(clearImmediateFallback, "clearImmediateFallback");
// node_modules/wrangler/_virtual_unenv_global_polyfill-set$immediate.js
globalThis.setImmediate = setImmediateFallback;
// node_modules/unenv/runtime/node/console/index.mjs
import { Writable } from "node:stream";
// node_modules/unenv/runtime/mock/proxy.mjs
var fn = /* @__PURE__ */ __name(function() {
}, "fn");
function createMock(name, overrides = {}) {
fn.prototype.name = name;
const props = {};
return new Proxy(fn, {
get(_target, prop) {
if (prop === "caller") {
return null;
}
if (prop === "__createMock__") {
return createMock;
}
if (prop === "__unenv__") {
return true;
}
if (prop in overrides) {
return overrides[prop];
}
return props[prop] = props[prop] || createMock(`${name}.${prop.toString()}`);
},
apply(_target, _this, _args) {
return createMock(`${name}()`);
},
construct(_target, _args, _newT) {
return createMock(`[${name}]`);
},
// @ts-ignore (ES6-only - removed in ES7)
// https://github.com/tc39/ecma262/issues/161
enumerate() {
return [];
}
});
}
__name(createMock, "createMock");
var proxy_default = createMock("mock");
// node_modules/unenv/runtime/node/console/index.mjs
var _console = globalThis.console;
var _ignoreErrors = true;
var _stderr = new Writable();
var _stdout = new Writable();
var log = _console?.log ?? noop_default;
var info = _console?.info ?? log;
var trace = _console?.trace ?? info;
var debug = _console?.debug ?? log;
var table = _console?.table ?? log;
var error = _console?.error ?? log;
var warn = _console?.warn ?? error;
var createTask = _console?.createTask ?? notImplemented("console.createTask");
var assert = notImplemented("console.assert");
var clear = _console?.clear ?? noop_default;
var count = _console?.count ?? noop_default;
var countReset = _console?.countReset ?? noop_default;
var dir = _console?.dir ?? noop_default;
var dirxml = _console?.dirxml ?? noop_default;
var group = _console?.group ?? noop_default;
var groupEnd = _console?.groupEnd ?? noop_default;
var groupCollapsed = _console?.groupCollapsed ?? noop_default;
var profile = _console?.profile ?? noop_default;
var profileEnd = _console?.profileEnd ?? noop_default;
var time = _console?.time ?? noop_default;
var timeEnd = _console?.timeEnd ?? noop_default;
var timeLog = _console?.timeLog ?? noop_default;
var timeStamp = _console?.timeStamp ?? noop_default;
var Console = _console?.Console ?? proxy_default.__createMock__("console.Console");
// node_modules/unenv/runtime/node/console/$cloudflare.mjs
var workerdConsole = globalThis["console"];
var {
assert: assert2,
clear: clear2,
// @ts-expect-error undocumented public API
context,
count: count2,
countReset: countReset2,
// @ts-expect-error undocumented public API
createTask: createTask2,
debug: debug2,
dir: dir2,
dirxml: dirxml2,
error: error2,
group: group2,
groupCollapsed: groupCollapsed2,
groupEnd: groupEnd2,
info: info2,
log: log2,
profile: profile2,
profileEnd: profileEnd2,
table: table2,
time: time2,
timeEnd: timeEnd2,
timeLog: timeLog2,
timeStamp: timeStamp2,
trace: trace2,
warn: warn2
} = workerdConsole;
Object.assign(workerdConsole, {
Console,
_ignoreErrors,
_stderr,
_stderrErrorHandler: noop_default,
_stdout,
_stdoutErrorHandler: noop_default,
_times: proxy_default
});
var cloudflare_default = workerdConsole;
// node_modules/wrangler/_virtual_unenv_global_polyfill-console.js
globalThis.console = cloudflare_default;
// node_modules/unenv/runtime/web/performance/_entry.mjs
var _supportedEntryTypes = [
"event",
// PerformanceEntry
"mark",
// PerformanceMark
"measure",
// PerformanceMeasure
"resource"
// PerformanceResourceTiming
];
var _PerformanceEntry = class {
__unenv__ = true;
detail;
entryType = "event";
name;
startTime;
constructor(name, options) {
this.name = name;
this.startTime = options?.startTime || performance.now();
this.detail = options?.detail;
}
get duration() {
return performance.now() - this.startTime;
}
toJSON() {
return {
name: this.name,
entryType: this.entryType,
startTime: this.startTime,
duration: this.duration,
detail: this.detail
};
}
};
__name(_PerformanceEntry, "_PerformanceEntry");
var PerformanceEntry = globalThis.PerformanceEntry || _PerformanceEntry;
var _PerformanceMark = class extends _PerformanceEntry {
entryType = "mark";
};
__name(_PerformanceMark, "_PerformanceMark");
var PerformanceMark = globalThis.PerformanceMark || _PerformanceMark;
var _PerformanceMeasure = class extends _PerformanceEntry {
entryType = "measure";
};
__name(_PerformanceMeasure, "_PerformanceMeasure");
var PerformanceMeasure = globalThis.PerformanceMeasure || _PerformanceMeasure;
var _PerformanceResourceTiming = class extends _PerformanceEntry {
entryType = "resource";
serverTiming = [];
connectEnd = 0;
connectStart = 0;
decodedBodySize = 0;
domainLookupEnd = 0;
domainLookupStart = 0;
encodedBodySize = 0;
fetchStart = 0;
initiatorType = "";
name = "";
nextHopProtocol = "";
redirectEnd = 0;
redirectStart = 0;
requestStart = 0;
responseEnd = 0;
responseStart = 0;
secureConnectionStart = 0;
startTime = 0;
transferSize = 0;
workerStart = 0;
};
__name(_PerformanceResourceTiming, "_PerformanceResourceTiming");
var PerformanceResourceTiming = globalThis.PerformanceResourceTiming || _PerformanceResourceTiming;
// node_modules/unenv/runtime/web/performance/_performance.mjs
var _timeOrigin = Date.now();
var _Performance = class {
__unenv__ = true;
timeOrigin = _timeOrigin;
eventCounts = /* @__PURE__ */ new Map();
_entries = [];
_resourceTimingBufferSize = 0;
navigation = proxy_default.__createMock__("PerformanceNavigation");
timing = proxy_default.__createMock__("PerformanceTiming");
onresourcetimingbufferfull = null;
now() {
if (globalThis?.performance?.now && this.timeOrigin === _timeOrigin) {
return globalThis.performance.now();
}
return Date.now() - this.timeOrigin;
}
clearMarks(markName) {
this._entries = markName ? this._entries.filter((e) => e.name !== markName) : this._entries.filter((e) => e.entryType !== "mark");
}
clearMeasures(measureName) {
this._entries = measureName ? this._entries.filter((e) => e.name !== measureName) : this._entries.filter((e) => e.entryType !== "measure");
}
clearResourceTimings() {
this._entries = this._entries.filter(
(e) => e.entryType !== "resource" || e.entryType !== "navigation"
);
}
getEntries() {
return this._entries;
}
getEntriesByName(name, type) {
return this._entries.filter(
(e) => e.name === name && (!type || e.entryType === type)
);
}
getEntriesByType(type) {
return this._entries.filter(
(e) => e.entryType === type
);
}
mark(name, options) {
const entry = new _PerformanceMark(name, options);
this._entries.push(entry);
return entry;
}
measure(measureName, startOrMeasureOptions, endMark) {
let start;
let end;
if (typeof startOrMeasureOptions === "string") {
start = this.getEntriesByName(startOrMeasureOptions, "mark")[0]?.startTime;
end = this.getEntriesByName(endMark, "mark")[0]?.startTime;
} else {
start = Number.parseFloat(startOrMeasureOptions?.start) || performance2.now();
end = Number.parseFloat(startOrMeasureOptions?.end) || performance2.now();
}
const entry = new _PerformanceMeasure(measureName, {
startTime: start,
detail: { start, end }
});
this._entries.push(entry);
return entry;
}
setResourceTimingBufferSize(maxSize) {
this._resourceTimingBufferSize = maxSize;
}
toJSON() {
return this;
}
addEventListener(type, listener, options) {
throw createNotImplementedError("Performance.addEventListener");
}
removeEventListener(type, listener, options) {
throw createNotImplementedError("Performance.removeEventListener");
}
dispatchEvent(event) {
throw createNotImplementedError("Performance.dispatchEvent");
}
};
__name(_Performance, "_Performance");
var Performance = globalThis.Performance || _Performance;
var performance2 = globalThis.performance || new Performance();
// node_modules/unenv/runtime/web/performance/_observer.mjs
var _PerformanceObserver = class {
__unenv__ = true;
_callback = null;
constructor(callback) {
this._callback = callback;
}
takeRecords() {
return [];
}
disconnect() {
throw createNotImplementedError("PerformanceObserver.disconnect");
}
observe(options) {
throw createNotImplementedError("PerformanceObserver.observe");
}
};
__name(_PerformanceObserver, "_PerformanceObserver");
__publicField(_PerformanceObserver, "supportedEntryTypes", _supportedEntryTypes);
var PerformanceObserver = globalThis.PerformanceObserver || _PerformanceObserver;
var _PerformanceObserverEntryList = class {
__unenv__ = true;
getEntries() {
return [];
}
getEntriesByName(_name, _type) {
return [];
}
getEntriesByType(type) {
return [];
}
};
__name(_PerformanceObserverEntryList, "_PerformanceObserverEntryList");
var PerformanceObserverEntryList = globalThis.PerformanceObserverEntryList || _PerformanceObserverEntryList;
// node_modules/unenv/runtime/polyfill/global-this.mjs
function getGlobal() {
if (typeof globalThis !== "undefined") {
return globalThis;
}
if (typeof self !== "undefined") {
return self;
}
if (typeof window !== "undefined") {
return window;
}
if (typeof global !== "undefined") {
return global;
}
return {};
}
__name(getGlobal, "getGlobal");
var global_this_default = getGlobal();
// node_modules/unenv/runtime/polyfill/performance.mjs
global_this_default.performance = global_this_default.performance || performance2;
global_this_default.Performance = global_this_default.Performance || Performance;
global_this_default.PerformanceEntry = global_this_default.PerformanceEntry || PerformanceEntry;
global_this_default.PerformanceMark = global_this_default.PerformanceMark || PerformanceMark;
global_this_default.PerformanceMeasure = global_this_default.PerformanceMeasure || PerformanceMeasure;
global_this_default.PerformanceObserver = global_this_default.PerformanceObserver || PerformanceObserver;
global_this_default.PerformanceObserverEntryList = global_this_default.PerformanceObserverEntryList || PerformanceObserverEntryList;
global_this_default.PerformanceResourceTiming = global_this_default.PerformanceResourceTiming || PerformanceResourceTiming;
var performance_default = global_this_default.performance;
// node_modules/wrangler/_virtual_unenv_global_polyfill-performance.js
globalThis.performance = performance_default;
// node_modules/unenv/runtime/mock/empty.mjs
var empty_default = Object.freeze(
Object.create(null, {
__unenv__: { get: () => true }
})
);
// node_modules/unenv/runtime/node/process/internal/env.mjs
var _envShim = /* @__PURE__ */ Object.create(null);
var _processEnv = globalThis.process?.env;
var _getEnv = /* @__PURE__ */ __name((useShim) => _processEnv || globalThis.__env__ || (useShim ? _envShim : globalThis), "_getEnv");
var env = new Proxy(_envShim, {
get(_, prop) {
const env22 = _getEnv();
return env22[prop] ?? _envShim[prop];
},
has(_, prop) {
const env22 = _getEnv();
return prop in env22 || prop in _envShim;
},
set(_, prop, value) {
const env22 = _getEnv(true);
env22[prop] = value;
return true;
},
deleteProperty(_, prop) {
const env22 = _getEnv(true);
delete env22[prop];
return true;
},
ownKeys() {
const env22 = _getEnv();
return Object.keys(env22);
}
});
// node_modules/unenv/runtime/node/process/internal/time.mjs
var hrtime = Object.assign(
/* @__PURE__ */ __name(function hrtime2(startTime) {
const now = Date.now();
const seconds = Math.trunc(now / 1e3);
const nanos = now % 1e3 * 1e6;
if (startTime) {
let diffSeconds = seconds - startTime[0];
let diffNanos = nanos - startTime[0];
if (diffNanos < 0) {
diffSeconds = diffSeconds - 1;
diffNanos = 1e9 + diffNanos;
}
return [diffSeconds, diffNanos];
}
return [seconds, nanos];
}, "hrtime2"),
{
bigint: /* @__PURE__ */ __name(function bigint() {
return BigInt(Date.now() * 1e6);
}, "bigint")
}
);
var nextTick = globalThis.queueMicrotask ? (cb, ...args) => {
globalThis.queueMicrotask(cb.bind(void 0, ...args));
} : _createNextTickWithTimeout();
function _createNextTickWithTimeout() {
let queue = [];
let draining = false;
let currentQueue;
let queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length > 0) {
queue = [...currentQueue, ...queue];
} else {
queueIndex = -1;
}
if (queue.length > 0) {
drainQueue();
}
}
__name(cleanUpNextTick, "cleanUpNextTick");
function drainQueue() {
if (draining) {
return;
}
const timeout = setTimeout(cleanUpNextTick);
draining = true;
let len = queue.length;
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex]();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = void 0;
draining = false;
clearTimeout(timeout);
}
__name(drainQueue, "drainQueue");
const nextTick22 = /* @__PURE__ */ __name((cb, ...args) => {
queue.push(cb.bind(void 0, ...args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue);
}
}, "nextTick2");
return nextTick22;
}
__name(_createNextTickWithTimeout, "_createNextTickWithTimeout");
// node_modules/unenv/runtime/node/process/internal/process.mjs
var title = "unenv";
var argv = [];
var version = "";
var versions = {
ares: "",
http_parser: "",
icu: "",
modules: "",
node: "",
openssl: "",
uv: "",
v8: "",
zlib: ""
};
function noop() {
return process;
}
__name(noop, "noop");
var on = noop;
var addListener = noop;
var once = noop;
var off = noop;
var removeListener = noop;
var removeAllListeners = noop;
var emit = /* @__PURE__ */ __name(function emit2(event) {
if (event === "message" || event === "multipleResolves") {
return process;
}
return false;
}, "emit2");
var prependListener = noop;
var prependOnceListener = noop;
var listeners = /* @__PURE__ */ __name(function(name) {
return [];
}, "listeners");
var listenerCount = /* @__PURE__ */ __name(() => 0, "listenerCount");
var binding = /* @__PURE__ */ __name(function(name) {
throw new Error("[unenv] process.binding is not supported");
}, "binding");
var _cwd = "/";
var cwd = /* @__PURE__ */ __name(function cwd2() {
return _cwd;
}, "cwd2");
var chdir = /* @__PURE__ */ __name(function chdir2(dir3) {
_cwd = dir3;
}, "chdir2");
var umask = /* @__PURE__ */ __name(function umask2() {
return 0;
}, "umask2");
var getegid = /* @__PURE__ */ __name(function getegid2() {
return 1e3;
}, "getegid2");
var geteuid = /* @__PURE__ */ __name(function geteuid2() {
return 1e3;
}, "geteuid2");
var getgid = /* @__PURE__ */ __name(function getgid2() {
return 1e3;
}, "getgid2");
var getuid = /* @__PURE__ */ __name(function getuid2() {
return 1e3;
}, "getuid2");
var getgroups = /* @__PURE__ */ __name(function getgroups2() {
return [];
}, "getgroups2");
var getBuiltinModule = /* @__PURE__ */ __name((_name) => void 0, "getBuiltinModule");
var abort = notImplemented("process.abort");
var allowedNodeEnvironmentFlags = /* @__PURE__ */ new Set();
var arch = "";
var argv0 = "";
var config = empty_default;
var connected = false;
var constrainedMemory = /* @__PURE__ */ __name(() => 0, "constrainedMemory");
var availableMemory = /* @__PURE__ */ __name(() => 0, "availableMemory");
var cpuUsage = notImplemented("process.cpuUsage");
var debugPort = 0;
var dlopen = notImplemented("process.dlopen");
var disconnect = noop;
var emitWarning = noop;
var eventNames = notImplemented("process.eventNames");
var execArgv = [];
var execPath = "";
var exit = notImplemented("process.exit");
var features = /* @__PURE__ */ Object.create({
inspector: void 0,
debug: void 0,
uv: void 0,
ipv6: void 0,
tls_alpn: void 0,
tls_sni: void 0,
tls_ocsp: void 0,
tls: void 0,
cached_builtins: void 0
});
var getActiveResourcesInfo = /* @__PURE__ */ __name(() => [], "getActiveResourcesInfo");
var getMaxListeners = notImplemented(
"process.getMaxListeners"
);
var kill = notImplemented("process.kill");
var memoryUsage = Object.assign(
() => ({
arrayBuffers: 0,
rss: 0,
external: 0,
heapTotal: 0,
heapUsed: 0
}),
{ rss: () => 0 }
);
var pid = 1e3;
var platform = "";
var ppid = 1e3;
var rawListeners = notImplemented(
"process.rawListeners"
);
var release = /* @__PURE__ */ Object.create({
name: "",
lts: "",
sourceUrl: void 0,
headersUrl: void 0
});
var report = /* @__PURE__ */ Object.create({
compact: void 0,
directory: void 0,
filename: void 0,
getReport: notImplemented("process.report.getReport"),
reportOnFatalError: void 0,
reportOnSignal: void 0,
reportOnUncaughtException: void 0,
signal: void 0,
writeReport: notImplemented("process.report.writeReport")
});
var resourceUsage = notImplemented(
"process.resourceUsage"
);
var setegid = notImplemented("process.setegid");
var seteuid = notImplemented("process.seteuid");
var setgid = notImplemented("process.setgid");
var setgroups = notImplemented("process.setgroups");
var setuid = notImplemented("process.setuid");
var setMaxListeners = notImplemented(
"process.setMaxListeners"
);
var setSourceMapsEnabled = notImplemented("process.setSourceMapsEnabled");
var stdout = proxy_default.__createMock__("process.stdout");
var stderr = proxy_default.__createMock__("process.stderr");
var stdin = proxy_default.__createMock__("process.stdin");
var traceDeprecation = false;
var uptime = /* @__PURE__ */ __name(() => 0, "uptime");
var exitCode = 0;
var setUncaughtExceptionCaptureCallback = notImplemented("process.setUncaughtExceptionCaptureCallback");
var hasUncaughtExceptionCaptureCallback = /* @__PURE__ */ __name(() => false, "hasUncaughtExceptionCaptureCallback");
var sourceMapsEnabled = false;
var loadEnvFile = notImplemented(
"process.loadEnvFile"
);
var mainModule = void 0;
var permission = {
has: () => false
};
var channel = {
ref() {
},
unref() {
}
};
var throwDeprecation = false;
var assert3 = notImplemented("process.assert");
var openStdin = notImplemented("process.openStdin");
var _debugEnd = notImplemented("process._debugEnd");
var _debugProcess = notImplemented("process._debugProcess");
var _fatalException = notImplemented("process._fatalException");
var _getActiveHandles = notImplemented("process._getActiveHandles");
var _getActiveRequests = notImplemented("process._getActiveRequests");
var _kill = notImplemented("process._kill");
var _preload_modules = [];
var _rawDebug = notImplemented("process._rawDebug");
var _startProfilerIdleNotifier = notImplemented(
"process._startProfilerIdleNotifier"
);
var _stopProfilerIdleNotifier = notImplemented(
"process.__stopProfilerIdleNotifier"
);
var _tickCallback = notImplemented("process._tickCallback");
var _linkedBinding = notImplemented("process._linkedBinding");
var domain = proxy_default.__createMock__("process.domain");
var initgroups = notImplemented("process.initgroups");
var moduleLoadList = [];
var reallyExit = noop;
var _exiting = false;
var _events = [];
var _eventsCount = 0;
var _maxListeners = 0;
var process = {
// @ts-expect-error
_events,
_eventsCount,
_exiting,
_maxListeners,
_debugEnd,
_debugProcess,
_fatalException,
_getActiveHandles,
_getActiveRequests,
_kill,
_preload_modules,
_rawDebug,
_startProfilerIdleNotifier,
_stopProfilerIdleNotifier,
_tickCallback,
domain,
initgroups,
moduleLoadList,
reallyExit,
exitCode,
abort,
addListener,
allowedNodeEnvironmentFlags,
hasUncaughtExceptionCaptureCallback,
setUncaughtExceptionCaptureCallback,
loadEnvFile,
sourceMapsEnabled,
throwDeprecation,
mainModule,
permission,
channel,
arch,
argv,
argv0,
assert: assert3,
binding,
chdir,
config,
connected,
constrainedMemory,
availableMemory,
cpuUsage,
cwd,
debugPort,
dlopen,
disconnect,
emit,
emitWarning,
env,
eventNames,
execArgv,
execPath,
exit,
features,
getBuiltinModule,
getegid,
geteuid,
getgid,
getgroups,
getuid,
getActiveResourcesInfo,
getMaxListeners,
hrtime,
kill,
listeners,
listenerCount,
memoryUsage,
nextTick,
on,
off,
once,
openStdin,
pid,
platform,
ppid,
prependListener,
prependOnceListener,
rawListeners,
release,
removeAllListeners,
removeListener,
report,
resourceUsage,
setegid,
seteuid,
setgid,
setgroups,
setuid,
setMaxListeners,
setSourceMapsEnabled,
stderr,
stdin,
stdout,
title,
traceDeprecation,
umask,
uptime,
version,
versions
};
// node_modules/unenv/runtime/node/process/$cloudflare.mjs
var unpatchedGlobalThisProcess = globalThis["process"];
var getBuiltinModule2 = unpatchedGlobalThisProcess.getBuiltinModule;
var workerdProcess = getBuiltinModule2("node:process");
var { env: env2, exit: exit2, nextTick: nextTick2, platform: platform2 } = workerdProcess;
var _process = {
/**
* manually unroll unenv-polyfilled-symbols to make it tree-shakeable
*/
// @ts-expect-error (not typed)
_debugEnd,
_debugProcess,
_events,
_eventsCount,
_exiting,
_fatalException,
_getActiveHandles,
_getActiveRequests,
_kill,
_linkedBinding,
_maxListeners,
_preload_modules,
_rawDebug,
_startProfilerIdleNotifier,
_stopProfilerIdleNotifier,
_tickCallback,
abort,
addListener,
allowedNodeEnvironmentFlags,
arch,
argv,
argv0,
assert: assert3,
availableMemory,
binding,
chdir,
config,
constrainedMemory,
cpuUsage,
cwd,
debugPort,
dlopen,
domain,
emit,
emitWarning,
eventNames,
execArgv,
execPath,
exit: exit2,
exitCode,
features,
getActiveResourcesInfo,
getMaxListeners,
getegid,
geteuid,
getgid,
getgroups,
getuid,
hasUncaughtExceptionCaptureCallback,
hrtime,
initgroups,
kill,
listenerCount,
listeners,
loadEnvFile,
memoryUsage,
moduleLoadList,
off,
on,
once,
openStdin,
pid,
platform: platform2,
ppid,
prependListener,
prependOnceListener,
rawListeners,
reallyExit,
release,
removeAllListeners,
removeListener,
report,
resourceUsage,
setMaxListeners,
setSourceMapsEnabled,
setUncaughtExceptionCaptureCallback,
setegid,
seteuid,
setgid,
setgroups,
setuid,
sourceMapsEnabled,
stderr,
stdin,
stdout,
title,
umask,
uptime,
version,
versions,
/**
* manually unroll workerd-polyfilled-symbols to make it tree-shakeable
*/
env: env2,
getBuiltinModule: getBuiltinModule2,
nextTick: nextTick2
};
var cloudflare_default2 = _process;
// node_modules/wrangler/_virtual_unenv_global_polyfill-process.js
globalThis.process = cloudflare_default2;
// src/worker.mjs
import { Buffer as Buffer2 } from "node:buffer";
var worker_default = {
async fetch(request) {
if (request.method === "OPTIONS") {
return handleOPTIONS();
}
const errHandler = /* @__PURE__ */ __name((err) => {
console.error(err);
return new Response(err.message, fixCors({ status: err.status ?? 500 }));
}, "errHandler");
try {
const auth = request.headers.get("Authorization");
const apiKey = auth?.split(" ")[1];
const assert4 = /* @__PURE__ */ __name((success) => {
if (!success) {
throw new HttpError("The specified HTTP method is not allowed for the requested resource", 400);
}
}, "assert");
const { pathname } = new URL(request.url);
switch (true) {
case pathname.endsWith("/chat/completions"):
assert4(request.method === "POST");
return handleCompletions(await request.json(), apiKey).catch(errHandler);
case pathname.endsWith("/embeddings"):
assert4(request.method === "POST");
return handleEmbeddings(await request.json(), apiKey).catch(errHandler);
case pathname.endsWith("/models"):
assert4(request.method === "GET");
return handleModels(apiKey).catch(errHandler);
default:
throw new HttpError("404 Not Found", 404);
}
} catch (err) {
return errHandler(err);
}
}
};
var HttpError = class extends Error {
constructor(message, status) {
super(message);
this.name = this.constructor.name;
this.status = status;
}
};
__name(HttpError, "HttpError");
var fixCors = /* @__PURE__ */ __name(({ headers, status, statusText }) => {
headers = new Headers(headers);
headers.set("Access-Control-Allow-Origin", "*");
return { headers, status, statusText };
}, "fixCors");
var handleOPTIONS = /* @__PURE__ */ __name(async () => {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Headers": "*"
}
});
}, "handleOPTIONS");
var BASE_URL = "https://generativelanguage.googleapis.com";
var API_VERSION = "v1beta";
var API_CLIENT = "genai-js/0.21.0";
var makeHeaders = /* @__PURE__ */ __name((apiKey, more) => ({
"x-goog-api-client": API_CLIENT,
...apiKey && { "x-goog-api-key": apiKey },
...more
}), "makeHeaders");
async function handleModels(apiKey) {
const response = await fetch(`${BASE_URL}/${API_VERSION}/models`, {
headers: makeHeaders(apiKey)
});
let { body } = response;
if (response.ok) {
const { models } = JSON.parse(await response.text());
body = JSON.stringify({
object: "list",
data: models.map(({ name }) => ({
id: name.replace("models/", ""),
object: "model",
created: 0,
owned_by: ""
}))
}, null, " ");
}
return new Response(body, fixCors(response));
}
__name(handleModels, "handleModels");
var DEFAULT_EMBEDDINGS_MODEL = "text-embedding-004";
async function handleEmbeddings(req, apiKey) {
if (typeof req.model !== "string") {
throw new HttpError("model is not specified", 400);
}
if (!Array.isArray(req.input)) {
req.input = [req.input];
}
let model;
if (req.model.startsWith("models/")) {
model = req.model;
} else {
req.model = DEFAULT_EMBEDDINGS_MODEL;
model = "models/" + req.model;
}
const response = await fetch(`${BASE_URL}/${API_VERSION}/${model}:batchEmbedContents`, {
method: "POST",
headers: makeHeaders(apiKey, { "Content-Type": "application/json" }),
body: JSON.stringify({
"requests": req.input.map((text) => ({
model,
content: { parts: { text } },
outputDimensionality: req.dimensions
}))
})
});
let { body } = response;
if (response.ok) {
const { embeddings } = JSON.parse(await response.text());
body = JSON.stringify({
object: "list",
data: embeddings.map(({ values }, index) => ({
object: "embedding",
index,
embedding: values
})),
model: req.model
}, null, " ");
}
return new Response(body, fixCors(response));
}
__name(handleEmbeddings, "handleEmbeddings");
var DEFAULT_MODEL = "gemini-1.5-pro-latest";
async function handleCompletions(req, apiKey) {
let model = DEFAULT_MODEL;
switch (true) {
case typeof req.model !== "string":
break;
case req.model.startsWith("models/"):
model = req.model.substring(7);
break;
case req.model.startsWith("gemini-"):
case req.model.startsWith("learnlm-"):
model = req.model;
}
const TASK = req.stream ? "streamGenerateContent" : "generateContent";
let url = `${BASE_URL}/${API_VERSION}/models/${model}:${TASK}`;
if (req.stream) {
url += "?alt=sse";
}
const response = await fetch(url, {
method: "POST",
headers: makeHeaders(apiKey, { "Content-Type": "application/json" }),
body: JSON.stringify(await transformRequest(req))
// try
});
let body = response.body;
if (response.ok) {
let id = generateChatcmplId();
if (req.stream) {
body = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new TransformStream({
transform: parseStream,
flush: parseStreamFlush,
buffer: ""
})).pipeThrough(new TransformStream({
transform: toOpenAiStream,
flush: toOpenAiStreamFlush,
streamIncludeUsage: req.stream_options?.include_usage,
model,
id,
last: []
})).pipeThrough(new TextEncoderStream());
} else {
body = await response.text();
body = processCompletionsResponse(JSON.parse(body), model, id);
}
}
return new Response(body, fixCors(response));
}
__name(handleCompletions, "handleCompletions");
var harmCategory = [
"HARM_CATEGORY_HATE_SPEECH",
"HARM_CATEGORY_SEXUALLY_EXPLICIT",
"HARM_CATEGORY_DANGEROUS_CONTENT",
"HARM_CATEGORY_HARASSMENT",
"HARM_CATEGORY_CIVIC_INTEGRITY"
];
var safetySettings = harmCategory.map((category) => ({
category,
threshold: "BLOCK_NONE"
}));
var fieldsMap = {
stop: "stopSequences",
n: "candidateCount",
// not for streaming
max_tokens: "maxOutputTokens",
max_completion_tokens: "maxOutputTokens",
temperature: "temperature",
top_p: "topP",
top_k: "topK",
// non-standard
frequency_penalty: "frequencyPenalty",
presence_penalty: "presencePenalty"
};
var transformConfig = /* @__PURE__ */ __name((req) => {
let cfg = {};
for (let key in req) {
const matchedKey = fieldsMap[key];
if (matchedKey) {
cfg[matchedKey] = req[key];
}
}
if (req.response_format) {
switch (req.response_format.type) {
case "json_schema":
cfg.responseSchema = req.response_format.json_schema?.schema;
if (cfg.responseSchema && "enum" in cfg.responseSchema) {
cfg.responseMimeType = "text/x.enum";
break;
}
case "json_object":
cfg.responseMimeType = "application/json";
break;
case "text":
cfg.responseMimeType = "text/plain";
break;
default:
throw new HttpError("Unsupported response_format.type", 400);
}
}
return cfg;
}, "transformConfig");
var parseImg = /* @__PURE__ */ __name(async (url) => {
let mimeType, data;
if (url.startsWith("http://") || url.startsWith("https://")) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`${response.status} ${response.statusText} (${url})`);
}
mimeType = response.headers.get("content-type");
data = Buffer2.from(await response.arrayBuffer()).toString("base64");
} catch (err) {
throw new Error("Error fetching image: " + err.toString());
}
} else {
const match = url.match(/^data:(?<mimeType>.*?)(;base64)?,(?<data>.*)$/);
if (!match) {
throw new Error("Invalid image data: " + url);
}
({ mimeType, data } = match.groups);
}
return {
inlineData: {
mimeType,
data
}
};
}, "parseImg");
var transformMsg = /* @__PURE__ */ __name(async ({ role, content }) => {
const parts = [];
if (!Array.isArray(content)) {
parts.push({ text: content });
return { role, parts };
}
for (const item of content) {
switch (item.type) {
case "text":
parts.push({ text: item.text });
break;
case "image_url":
parts.push(await parseImg(item.image_url.url));
break;
case "input_audio":
parts.push({
inlineData: {
mimeType: "audio/" + item.input_audio.format,
data: item.input_audio.data
}
});
break;
default:
throw new TypeError(`Unknown "content" item type: "${item.type}"`);
}
}
return { role, parts };
}, "transformMsg");
var transformMessages = /* @__PURE__ */ __name(async (messages) => {
if (!messages) {
return;
}
const contents = [];
let system_instruction;
for (const item of messages) {
if (item.role === "system") {
delete item.role;
system_instruction = await transformMsg(item);
} else {
item.role = item.role === "assistant" ? "model" : "user";
contents.push(await transformMsg(item));
}
}
if (system_instruction && contents.length === 0) {
contents.push({ role: "model", parts: { text: " " } });
}
return { system_instruction, contents };
}, "transformMessages");
var transformRequest = /* @__PURE__ */ __name(async (req) => ({
...await transformMessages(req.messages),
safetySettings,
generationConfig: transformConfig(req)
}), "transformRequest");
var generateChatcmplId = /* @__PURE__ */ __name(() => {
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const randomChar = /* @__PURE__ */ __name(() => characters[Math.floor(Math.random() * characters.length)], "randomChar");
return "chatcmpl-" + Array.from({ length: 29 }, randomChar).join("");
}, "generateChatcmplId");
var reasonsMap = {
//https://ai.google.dev/api/rest/v1/GenerateContentResponse#finishreason
//"FINISH_REASON_UNSPECIFIED": // Default value. This value is unused.
"STOP": "stop",
"MAX_TOKENS": "length",
"SAFETY": "content_filter",
"RECITATION": "content_filter"
//"OTHER": "OTHER",
// :"function_call",
};
var SEP = "\n\n|>";
var transformCandidates = /* @__PURE__ */ __name((key, cand) => ({
index: cand.index || 0,
// 0-index is absent in new -002 models response
[key]: {
role: "assistant",
content: cand.content?.parts.map((p) => p.text).join(SEP)
},
logprobs: null,
finish_reason: reasonsMap[cand.finishReason] || cand.finishReason
}), "transformCandidates");
var transformCandidatesMessage = transformCandidates.bind(null, "message");
var transformCandidatesDelta = transformCandidates.bind(null, "delta");
var transformUsage = /* @__PURE__ */ __name((data) => ({
completion_tokens: data.candidatesTokenCount,
prompt_tokens: data.promptTokenCount,
total_tokens: data.totalTokenCount
}), "transformUsage");
var processCompletionsResponse = /* @__PURE__ */ __name((data, model, id) => {
return JSON.stringify({
id,
choices: data.candidates.map(transformCandidatesMessage),
created: Math.floor(Date.now() / 1e3),
model,
//system_fingerprint: "fp_69829325d0",
object: "chat.completion",
usage: transformUsage(data.usageMetadata)
});
}, "processCompletionsResponse");
var responseLineRE = /^data: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
async function parseStream(chunk, controller) {
chunk = await chunk;
if (!chunk) {
return;
}
this.buffer += chunk;
do {
const match = this.buffer.match(responseLineRE);
if (!match) {
break;
}
controller.enqueue(match[1]);
this.buffer = this.buffer.substring(match[0].length);
} while (true);
}
__name(parseStream, "parseStream");
async function parseStreamFlush(controller) {
if (this.buffer) {
console.error("Invalid data:", this.buffer);
controller.enqueue(this.buffer);
}
}
__name(parseStreamFlush, "parseStreamFlush");
function transformResponseStream(data, stop, first) {
const item = transformCandidatesDelta(data.candidates[0]);
if (stop) {
item.delta = {};
} else {
item.finish_reason = null;
}
if (first) {
item.delta.content = "";
} else {
delete item.delta.role;
}
const output = {
id: this.id,
choices: [item],
created: Math.floor(Date.now() / 1e3),
model: this.model,
//system_fingerprint: "fp_69829325d0",
object: "chat.completion.chunk"
};
if (data.usageMetadata && this.streamIncludeUsage) {
output.usage = stop ? transformUsage(data.usageMetadata) : null;
}
return "data: " + JSON.stringify(output) + delimiter;
}
__name(transformResponseStream, "transformResponseStream");
var delimiter = "\n\n";
async function toOpenAiStream(chunk, controller) {
const transform = transformResponseStream.bind(this);
const line = await chunk;
if (!line) {
return;
}
let data;
try {
data = JSON.parse(line);
} catch (err) {
console.error(line);
console.error(err);
const length = this.last.length || 1;
const candidates = Array.from({ length }, (_, index) => ({
finishReason: "error",
content: { parts: [{ text: err }] },
index
}));
data = { candidates };
}
const cand = data.candidates[0];
console.assert(data.candidates.length === 1, "Unexpected candidates count: %d", data.candidates.length);
cand.index = cand.index || 0;
if (!this.last[cand.index]) {
controller.enqueue(transform(data, false, "first"));
}
this.last[cand.index] = data;
if (cand.content) {
controller.enqueue(transform(data));
}
}
__name(toOpenAiStream, "toOpenAiStream");
async function toOpenAiStreamFlush(controller) {
const transform = transformResponseStream.bind(this);
if (this.last.length > 0) {
for (const data of this.last) {
controller.enqueue(transform(data, "stop"));
}
controller.enqueue("data: [DONE]" + delimiter);
}
}
__name(toOpenAiStreamFlush, "toOpenAiStreamFlush");
export {
worker_default as default
};
//# sourceMappingURL=worker.js.map
Docker镜像
注:此应用需要绑定如下域名:
docker.xxx.com
quay.xxx.com
gcr.xxx.com
ghcr.xxx.com
k8s-gcr.xxx.com
k8s.xxx.com
cloudsmith.xxx.com
将xxx.com改为你的域名
(() => {
// src/index.js
addEventListener("fetch", (event) => {
event.passThroughOnException();
event.respondWith(handleRequest(event.request));
});
var routes = {
"docker.xxx.com": "https://registry-1.docker.io",
"quay.xxx.com": "https://quay.io",
"gcr.xxx.com": "https://gcr.io",
"k8s-gcr.xxx.com": "https://k8s.gcr.io",
"k8s.xxx.com": "https://registry.k8s.io",
"ghcr.xxx.com": "https://ghcr.io",
"cloudsmith.xxx.com": "https://docker.cloudsmith.io"
};
function routeByHosts(host) {
if (host in routes) {
return routes[host];
}
if (MODE == "debug") {
return TARGET_UPSTREAM;
}
return "";
}
async function handleRequest(request) {
const url = new URL(request.url);
const upstream = routeByHosts(url.hostname);
if (upstream === "") {
return new Response(
JSON.stringify({
routes
}),
{
status: 404
}
);
}
if (url.pathname == "/v2/") {
const newUrl2 = new URL(upstream + "/v2/");
const resp = await fetch(newUrl2.toString(), {
method: "GET",
redirect: "follow"
});
if (resp.status === 200) {
} else if (resp.status === 401) {
const headers = new Headers();
if (MODE == "debug") {
headers.set(
"Www-Authenticate",
`Bearer realm="${LOCAL_ADDRESS}/v2/auth",service="cloudflare-docker-proxy"`
);
} else {
headers.set(
"Www-Authenticate",
`Bearer realm="https://${url.hostname}/v2/auth",service="cloudflare-docker-proxy"`
);
}
return new Response(JSON.stringify({ message: "UNAUTHORIZED" }), {
status: 401,
headers
});
} else {
return resp;
}
}
if (url.pathname == "/v2/auth") {
const newUrl2 = new URL(upstream + "/v2/");
const resp = await fetch(newUrl2.toString(), {
method: "GET",
redirect: "follow"
});
if (resp.status !== 401) {
return resp;
}
const authenticateStr = resp.headers.get("WWW-Authenticate");
if (authenticateStr === null) {
return resp;
}
const wwwAuthenticate = parseAuthenticate(authenticateStr);
return await fetchToken(wwwAuthenticate, url.searchParams);
}
const newUrl = new URL(upstream + url.pathname);
const newReq = new Request(newUrl, {
method: request.method,
headers: request.headers,
redirect: "follow"
});
return await fetch(newReq);
}
function parseAuthenticate(authenticateStr) {
const re = /(?<=\=")(?:\\.|[^"\\])*(?=")/g;
const matches = authenticateStr.match(re);
if (matches === null || matches.length < 2) {
throw new Error(`invalid Www-Authenticate Header: ${authenticateStr}`);
}
return {
realm: matches[0],
service: matches[1]
};
}
async function fetchToken(wwwAuthenticate, searchParams) {
const url = new URL(wwwAuthenticate.realm);
if (wwwAuthenticate.service.length) {
url.searchParams.set("service", wwwAuthenticate.service);
}
if (searchParams.get("scope")) {
url.searchParams.set("scope", searchParams.get("scope"));
}
return await fetch(url, { method: "GET", headers: {} });
}
})();
//# sourceMappingURL=index.js.map
评论