V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  Qist  ›  全部回复第 1 页 / 共 1 页
回复总数  2
170 天前
回复了 muzihuaner 创建的主题 分享创造 用 cloudflare worker 搭建一个 Docker 镜像
addEventListener("fetch", (event) => {
event.passThroughOnException();
event.respondWith(handleRequest(event.request));
});

const routes = {
"docker.域名": "https://registry-1.docker.io",
"quay.域名": "https://quay.io",
"gcr.域名": "https://gcr.io",
"k8s-gcr.域名": "https://k8s.gcr.io",
"k8s.域名": "https://registry.k8s.io",
"ghcr.域名": "https://ghcr.io",
"cloudsmith.域名": "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) {
let url = new URL(request.url);
const upstream = routeByHosts(url.hostname);
if (upstream === "") {
return new Response(
JSON.stringify({
routes: routes,
}),
{
status: 404,
}
);
}
if (upstream === "https://registry-1.docker.io") {
// Modify URL if necessary based on search parameters and encoded characters
if (!/%2F/.test(url.search) && /%3A/.test(url.toString())) {
let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F');
url = new URL(modifiedUrl);
}

// Append 'library' to the pathname if necessary
const libraryPathPattern = /^\/v2\/[^/]+\/[^/]+\/[^/]+$/;
const libraryPrefixPattern = /^\/v2\/library/;
if (libraryPathPattern.test(url.pathname) && !libraryPrefixPattern.test(url.pathname)) {
url.pathname = url.pathname.replace(/\/v2\//, '/v2/library/');
}
}
// check if need to authenticate
if (url.pathname == "/v2/") {
const newUrl = new URL(upstream + "/v2/");
const resp = await fetch(newUrl.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: headers,
});
} else {
return resp;
}
}
// get token
if (url.pathname == "/v2/auth") {
const newUrl = new URL(upstream + "/v2/");
const resp = await fetch(newUrl.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);
}
// foward requests
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) {
// sample: Bearer realm="https://auth.ipv6.docker.com/token",service="registry.docker.io"
// match strings after =" and before "
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: {} });
}
2023-02-16 09:18:59 +08:00
回复了 Mr0C 创建的主题 问与答 如何提高和异性聊天的能力?
开好车,根本不需要你会啥沟通。或者进入一家大企业随时无意发些朋友圈,脉脉圈,送上门的很多。
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1073 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 11ms · UTC 18:59 · PVG 02:59 · LAX 10:59 · JFK 13:59
Developed with CodeLauncher
♥ Do have faith in what you're doing.