mirror of
https://github.com/ciiiii/cloudflare-docker-proxy.git
synced 2025-12-06 14:42:51 +08:00
Compare commits
2 Commits
yscai/priv
...
yscai/dock
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c737c70c48 | ||
|
|
109f2d4d41 |
71
src/index.js
71
src/index.js
@@ -3,8 +3,10 @@ addEventListener("fetch", (event) => {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
});
|
||||
|
||||
const dockerHub = "https://registry-1.docker.io";
|
||||
|
||||
const routes = {
|
||||
"docker.libcuda.so": "https://registry-1.docker.io",
|
||||
"docker.libcuda.so": dockerHub,
|
||||
"quay.libcuda.so": "https://quay.io",
|
||||
"gcr.libcuda.so": "https://gcr.io",
|
||||
"k8s-gcr.libcuda.so": "https://k8s.gcr.io",
|
||||
@@ -25,27 +27,6 @@ function routeByHosts(host) {
|
||||
|
||||
async function handleRequest(request) {
|
||||
const url = new URL(request.url);
|
||||
const authorization = request.headers.get("Authorization");
|
||||
if (url.pathname == "/v2/") {
|
||||
if (authorization === null || authorization === "") {
|
||||
const headers = new Headers();
|
||||
if (MODE == "debug") {
|
||||
headers.set(
|
||||
"Www-Authenticate",
|
||||
`Bearer realm="http://${url.host}/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,
|
||||
});
|
||||
}
|
||||
}
|
||||
const upstream = routeByHosts(url.hostname);
|
||||
if (upstream === "") {
|
||||
return new Response(
|
||||
@@ -57,20 +38,25 @@ async function handleRequest(request) {
|
||||
}
|
||||
);
|
||||
}
|
||||
// check if need to authenticate
|
||||
const isDockerHub = upstream == dockerHub;
|
||||
const authorization = request.headers.get("Authorization");
|
||||
if (url.pathname == "/v2/") {
|
||||
const newUrl = new URL(upstream + "/v2/");
|
||||
const headers = new Headers();
|
||||
if (authorization) {
|
||||
headers.set("Authorization", authorization);
|
||||
}
|
||||
// check if need to authenticate
|
||||
const resp = await fetch(newUrl.toString(), {
|
||||
method: "GET",
|
||||
headers: headers,
|
||||
redirect: "follow",
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
} else if (resp.status === 401) {
|
||||
const headers = new Headers();
|
||||
if (resp.status === 401) {
|
||||
if (MODE == "debug") {
|
||||
headers.set(
|
||||
"Www-Authenticate",
|
||||
`Bearer realm="${LOCAL_ADDRESS}/v2/auth",service="cloudflare-docker-proxy"`
|
||||
`Bearer realm="http://${url.host}/v2/auth",service="cloudflare-docker-proxy"`
|
||||
);
|
||||
} else {
|
||||
headers.set(
|
||||
@@ -101,7 +87,28 @@ async function handleRequest(request) {
|
||||
return resp;
|
||||
}
|
||||
const wwwAuthenticate = parseAuthenticate(authenticateStr);
|
||||
return await fetchToken(wwwAuthenticate, url.searchParams, authorization);
|
||||
let scope = url.searchParams.get("scope");
|
||||
// autocomplete repo part into scope for DockerHub library images
|
||||
// Example: repository:busybox:pull => repository:library/busybox:pull
|
||||
if (scope && isDockerHub) {
|
||||
let scopeParts = scope.split(":");
|
||||
if (scopeParts.length == 3 && !scopeParts[1].includes("/")) {
|
||||
scopeParts[1] = "library/" + scopeParts[1];
|
||||
scope = scopeParts.join(":");
|
||||
}
|
||||
}
|
||||
return await fetchToken(wwwAuthenticate, scope, authorization);
|
||||
}
|
||||
// redirect for DockerHub library images
|
||||
// Example: /v2/busybox/manifests/latest => /v2/library/busybox/manifests/latest
|
||||
if (isDockerHub) {
|
||||
const pathParts = url.pathname.split("/");
|
||||
if (pathParts.length == 5) {
|
||||
pathParts.splice(2, 0, "library");
|
||||
const redirectUrl = new URL(url);
|
||||
redirectUrl.pathname = pathParts.join("/");
|
||||
return Response.redirect(redirectUrl, 301);
|
||||
}
|
||||
}
|
||||
// foward requests
|
||||
const newUrl = new URL(upstream + url.pathname);
|
||||
@@ -118,7 +125,7 @@ function parseAuthenticate(authenticateStr) {
|
||||
// match strings after =" and before "
|
||||
const re = /(?<=\=")(?:\\.|[^"\\])*(?=")/g;
|
||||
const matches = authenticateStr.match(re);
|
||||
if (matches === null || matches.length < 2) {
|
||||
if (matches == null || matches.length < 2) {
|
||||
throw new Error(`invalid Www-Authenticate Header: ${authenticateStr}`);
|
||||
}
|
||||
return {
|
||||
@@ -127,13 +134,13 @@ function parseAuthenticate(authenticateStr) {
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchToken(wwwAuthenticate, searchParams, authorization) {
|
||||
async function fetchToken(wwwAuthenticate, scope, authorization) {
|
||||
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"));
|
||||
if (scope) {
|
||||
url.searchParams.set("scope", scope);
|
||||
}
|
||||
headers = new Headers();
|
||||
if (authorization) {
|
||||
|
||||
@@ -11,7 +11,6 @@ upstream_protocol="https"
|
||||
|
||||
[vars]
|
||||
MODE="production"
|
||||
LOCAL_ADDRESS=""
|
||||
TARGET_UPSTREAM=""
|
||||
|
||||
[env.dev.vars]
|
||||
|
||||
Reference in New Issue
Block a user