diff --git a/.wrangler/tmp/bundle-aZ8oNd/checked-fetch.js b/.wrangler/tmp/bundle-aZ8oNd/checked-fetch.js
new file mode 100644
index 0000000..8c007fd
--- /dev/null
+++ b/.wrangler/tmp/bundle-aZ8oNd/checked-fetch.js
@@ -0,0 +1,30 @@
+const urls = new Set();
+
+function checkURL(request, init) {
+ const url =
+ request instanceof URL
+ ? request
+ : new URL(
+ (typeof request === "string"
+ ? new Request(request, init)
+ : request
+ ).url
+ );
+ if (url.port && url.port !== "443" && url.protocol === "https:") {
+ if (!urls.has(url.toString())) {
+ urls.add(url.toString());
+ console.warn(
+ `WARNING: known issue with \`fetch()\` requests to custom HTTPS ports in published Workers:\n` +
+ ` - ${url.toString()} - the custom port will be ignored when the Worker is published using the \`wrangler deploy\` command.\n`
+ );
+ }
+ }
+}
+
+globalThis.fetch = new Proxy(globalThis.fetch, {
+ apply(target, thisArg, argArray) {
+ const [request, init] = argArray;
+ checkURL(request, init);
+ return Reflect.apply(target, thisArg, argArray);
+ },
+});
diff --git a/.wrangler/tmp/bundle-aZ8oNd/middleware-insertion-facade.js b/.wrangler/tmp/bundle-aZ8oNd/middleware-insertion-facade.js
new file mode 100644
index 0000000..19ffeda
--- /dev/null
+++ b/.wrangler/tmp/bundle-aZ8oNd/middleware-insertion-facade.js
@@ -0,0 +1,4 @@
+ import { __facade_registerInternal__ } from "C:\\Users\\wood\\codespace\\hammal\\node_modules\\.pnpm\\wrangler@3.60.0_@cloudflare+workers-types@2.0.0\\node_modules\\wrangler\\templates\\middleware\\loader-sw.ts";
+ import * as __MIDDLEWARE_0__ from "C:\\Users\\wood\\codespace\\hammal\\node_modules\\.pnpm\\wrangler@3.60.0_@cloudflare+workers-types@2.0.0\\node_modules\\wrangler\\templates\\middleware\\middleware-ensure-req-body-drained.ts";
+import * as __MIDDLEWARE_1__ from "C:\\Users\\wood\\codespace\\hammal\\node_modules\\.pnpm\\wrangler@3.60.0_@cloudflare+workers-types@2.0.0\\node_modules\\wrangler\\templates\\middleware\\middleware-miniflare3-json-error.ts";
+ __facade_registerInternal__([__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default])
\ No newline at end of file
diff --git a/.wrangler/tmp/dev-76tGCa/index.js b/.wrangler/tmp/dev-76tGCa/index.js
new file mode 100644
index 0000000..61ff281
--- /dev/null
+++ b/.wrangler/tmp/dev-76tGCa/index.js
@@ -0,0 +1,600 @@
+"use strict";
+(() => {
+ // .wrangler/tmp/bundle-aZ8oNd/checked-fetch.js
+ var urls = /* @__PURE__ */ new Set();
+ function checkURL(request, init) {
+ const url = request instanceof URL ? request : new URL(
+ (typeof request === "string" ? new Request(request, init) : request).url
+ );
+ if (url.port && url.port !== "443" && url.protocol === "https:") {
+ if (!urls.has(url.toString())) {
+ urls.add(url.toString());
+ console.warn(
+ `WARNING: known issue with \`fetch()\` requests to custom HTTPS ports in published Workers:
+ - ${url.toString()} - the custom port will be ignored when the Worker is published using the \`wrangler deploy\` command.
+`
+ );
+ }
+ }
+ }
+ globalThis.fetch = new Proxy(globalThis.fetch, {
+ apply(target, thisArg, argArray) {
+ const [request, init] = argArray;
+ checkURL(request, init);
+ return Reflect.apply(target, thisArg, argArray);
+ }
+ });
+
+ // node_modules/.pnpm/wrangler@3.60.0_@cloudflare+workers-types@2.0.0/node_modules/wrangler/templates/middleware/common.ts
+ var __facade_middleware__ = [];
+ function __facade_register__(...args) {
+ __facade_middleware__.push(...args.flat());
+ }
+ function __facade_registerInternal__(...args) {
+ __facade_middleware__.unshift(...args.flat());
+ }
+ function __facade_invokeChain__(request, env, ctx, dispatch, middlewareChain) {
+ const [head, ...tail] = middlewareChain;
+ const middlewareCtx = {
+ dispatch,
+ next(newRequest, newEnv) {
+ return __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail);
+ }
+ };
+ return head(request, env, ctx, middlewareCtx);
+ }
+ function __facade_invoke__(request, env, ctx, dispatch, finalMiddleware) {
+ return __facade_invokeChain__(request, env, ctx, dispatch, [
+ ...__facade_middleware__,
+ finalMiddleware
+ ]);
+ }
+
+ // node_modules/.pnpm/wrangler@3.60.0_@cloudflare+workers-types@2.0.0/node_modules/wrangler/templates/middleware/loader-sw.ts
+ var __FACADE_EVENT_TARGET__;
+ if (globalThis.MINIFLARE) {
+ __FACADE_EVENT_TARGET__ = new (Object.getPrototypeOf(WorkerGlobalScope))();
+ } else {
+ __FACADE_EVENT_TARGET__ = new EventTarget();
+ }
+ function __facade_isSpecialEvent__(type) {
+ return type === "fetch" || type === "scheduled";
+ }
+ var __facade__originalAddEventListener__ = globalThis.addEventListener;
+ var __facade__originalRemoveEventListener__ = globalThis.removeEventListener;
+ var __facade__originalDispatchEvent__ = globalThis.dispatchEvent;
+ globalThis.addEventListener = function(type, listener, options) {
+ if (__facade_isSpecialEvent__(type)) {
+ __FACADE_EVENT_TARGET__.addEventListener(
+ type,
+ listener,
+ options
+ );
+ } else {
+ __facade__originalAddEventListener__(type, listener, options);
+ }
+ };
+ globalThis.removeEventListener = function(type, listener, options) {
+ if (__facade_isSpecialEvent__(type)) {
+ __FACADE_EVENT_TARGET__.removeEventListener(
+ type,
+ listener,
+ options
+ );
+ } else {
+ __facade__originalRemoveEventListener__(type, listener, options);
+ }
+ };
+ globalThis.dispatchEvent = function(event) {
+ if (__facade_isSpecialEvent__(event.type)) {
+ return __FACADE_EVENT_TARGET__.dispatchEvent(event);
+ } else {
+ return __facade__originalDispatchEvent__(event);
+ }
+ };
+ globalThis.addMiddleware = __facade_register__;
+ globalThis.addMiddlewareInternal = __facade_registerInternal__;
+ var __facade_waitUntil__ = Symbol("__facade_waitUntil__");
+ var __facade_response__ = Symbol("__facade_response__");
+ var __facade_dispatched__ = Symbol("__facade_dispatched__");
+ var __Facade_ExtendableEvent__ = class extends Event {
+ [__facade_waitUntil__] = [];
+ waitUntil(promise) {
+ if (!(this instanceof __Facade_ExtendableEvent__)) {
+ throw new TypeError("Illegal invocation");
+ }
+ this[__facade_waitUntil__].push(promise);
+ }
+ };
+ var __Facade_FetchEvent__ = class extends __Facade_ExtendableEvent__ {
+ #request;
+ #passThroughOnException;
+ [__facade_response__];
+ [__facade_dispatched__] = false;
+ constructor(type, init) {
+ super(type);
+ this.#request = init.request;
+ this.#passThroughOnException = init.passThroughOnException;
+ }
+ get request() {
+ return this.#request;
+ }
+ respondWith(response) {
+ if (!(this instanceof __Facade_FetchEvent__)) {
+ throw new TypeError("Illegal invocation");
+ }
+ if (this[__facade_response__] !== void 0) {
+ throw new DOMException(
+ "FetchEvent.respondWith() has already been called; it can only be called once.",
+ "InvalidStateError"
+ );
+ }
+ if (this[__facade_dispatched__]) {
+ throw new DOMException(
+ "Too late to call FetchEvent.respondWith(). It must be called synchronously in the event handler.",
+ "InvalidStateError"
+ );
+ }
+ this.stopImmediatePropagation();
+ this[__facade_response__] = response;
+ }
+ passThroughOnException() {
+ if (!(this instanceof __Facade_FetchEvent__)) {
+ throw new TypeError("Illegal invocation");
+ }
+ this.#passThroughOnException();
+ }
+ };
+ var __Facade_ScheduledEvent__ = class extends __Facade_ExtendableEvent__ {
+ #scheduledTime;
+ #cron;
+ #noRetry;
+ constructor(type, init) {
+ super(type);
+ this.#scheduledTime = init.scheduledTime;
+ this.#cron = init.cron;
+ this.#noRetry = init.noRetry;
+ }
+ get scheduledTime() {
+ return this.#scheduledTime;
+ }
+ get cron() {
+ return this.#cron;
+ }
+ noRetry() {
+ if (!(this instanceof __Facade_ScheduledEvent__)) {
+ throw new TypeError("Illegal invocation");
+ }
+ this.#noRetry();
+ }
+ };
+ __facade__originalAddEventListener__("fetch", (event) => {
+ const ctx = {
+ waitUntil: event.waitUntil.bind(event),
+ passThroughOnException: event.passThroughOnException.bind(event)
+ };
+ const __facade_sw_dispatch__ = function(type, init) {
+ if (type === "scheduled") {
+ const facadeEvent = new __Facade_ScheduledEvent__("scheduled", {
+ scheduledTime: Date.now(),
+ cron: init.cron ?? "",
+ noRetry() {
+ }
+ });
+ __FACADE_EVENT_TARGET__.dispatchEvent(facadeEvent);
+ event.waitUntil(Promise.all(facadeEvent[__facade_waitUntil__]));
+ }
+ };
+ const __facade_sw_fetch__ = function(request, _env, ctx2) {
+ const facadeEvent = new __Facade_FetchEvent__("fetch", {
+ request,
+ passThroughOnException: ctx2.passThroughOnException
+ });
+ __FACADE_EVENT_TARGET__.dispatchEvent(facadeEvent);
+ facadeEvent[__facade_dispatched__] = true;
+ event.waitUntil(Promise.all(facadeEvent[__facade_waitUntil__]));
+ const response = facadeEvent[__facade_response__];
+ if (response === void 0) {
+ throw new Error("No response!");
+ }
+ return response;
+ };
+ event.respondWith(
+ __facade_invoke__(
+ event.request,
+ globalThis,
+ ctx,
+ __facade_sw_dispatch__,
+ __facade_sw_fetch__
+ )
+ );
+ });
+ __facade__originalAddEventListener__("scheduled", (event) => {
+ const facadeEvent = new __Facade_ScheduledEvent__("scheduled", {
+ scheduledTime: event.scheduledTime,
+ cron: event.cron,
+ noRetry: event.noRetry.bind(event)
+ });
+ __FACADE_EVENT_TARGET__.dispatchEvent(facadeEvent);
+ event.waitUntil(Promise.all(facadeEvent[__facade_waitUntil__]));
+ });
+
+ // node_modules/.pnpm/wrangler@3.60.0_@cloudflare+workers-types@2.0.0/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts
+ var drainBody = async (request, env, _ctx, middlewareCtx) => {
+ try {
+ return await middlewareCtx.next(request, env);
+ } finally {
+ try {
+ if (request.body !== null && !request.bodyUsed) {
+ const reader = request.body.getReader();
+ while (!(await reader.read()).done) {
+ }
+ }
+ } catch (e) {
+ console.error("Failed to drain the unused request body.", e);
+ }
+ }
+ };
+ var middleware_ensure_req_body_drained_default = drainBody;
+
+ // node_modules/.pnpm/wrangler@3.60.0_@cloudflare+workers-types@2.0.0/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts
+ function reduceError(e) {
+ return {
+ name: e?.name,
+ message: e?.message ?? String(e),
+ stack: e?.stack,
+ cause: e?.cause === void 0 ? void 0 : reduceError(e.cause)
+ };
+ }
+ var jsonError = async (request, env, _ctx, middlewareCtx) => {
+ try {
+ return await middlewareCtx.next(request, env);
+ } catch (e) {
+ const error = reduceError(e);
+ return Response.json(error, {
+ status: 500,
+ headers: { "MF-Experimental-Error-Stack": "true" }
+ });
+ }
+ };
+ var middleware_miniflare3_json_error_default = jsonError;
+
+ // .wrangler/tmp/bundle-aZ8oNd/middleware-insertion-facade.js
+ __facade_registerInternal__([middleware_ensure_req_body_drained_default, middleware_miniflare3_json_error_default]);
+
+ // src/token.ts
+ function parseAuthenticateStr(authenticateStr) {
+ const bearer = authenticateStr.split(/\s+/, 2);
+ if (bearer.length != 2 && bearer[0].toLowerCase() !== "bearer") {
+ throw new Error(`Invalid Www-Authenticate ${authenticateStr}`);
+ }
+ const params = bearer[1].split(",");
+ let get_param = function(name) {
+ for (const param of params) {
+ const kvPair = param.split("=", 2);
+ if (kvPair.length !== 2 || kvPair[0] !== name) {
+ continue;
+ }
+ return kvPair[1].replace(/['"]+/g, "");
+ }
+ return "";
+ };
+ return {
+ realm: get_param("realm"),
+ service: get_param("service"),
+ scope: get_param("scope")
+ };
+ }
+ var TokenProvider = class {
+ username;
+ password;
+ constructor(username, password) {
+ this.username = username;
+ this.password = password;
+ }
+ async authenticateCacheKey(wwwAuthenticate) {
+ const keyStr = `${this.username}:${this.password}/${wwwAuthenticate.realm}/${wwwAuthenticate.service}/${wwwAuthenticate.scope}`;
+ const keyStrText = new TextEncoder().encode(keyStr);
+ const digestArray = await crypto.subtle.digest({ name: "SHA-256" }, keyStrText);
+ const digestUint8Array = new Uint8Array(digestArray);
+ let hexArray = [];
+ for (const num of digestUint8Array) {
+ hexArray.push(num.toString(16));
+ }
+ const digestHex = hexArray.join("");
+ return `token/${digestHex}`;
+ }
+ async tokenFromCache(cacheKey) {
+ const value = await HAMMAL_CACHE.get(cacheKey);
+ if (value === null) {
+ return null;
+ }
+ return JSON.parse(value);
+ }
+ async tokenToCache(cacheKey, token) {
+ await HAMMAL_CACHE.put(cacheKey, JSON.stringify(token), { expirationTtl: token.expires_in });
+ }
+ async fetchToken(wwwAuthenticate) {
+ const url = new URL(wwwAuthenticate.realm);
+ if (wwwAuthenticate.service.length) {
+ url.searchParams.set("service", wwwAuthenticate.service);
+ }
+ if (wwwAuthenticate.scope.length) {
+ url.searchParams.set("scope", wwwAuthenticate.scope);
+ }
+ const response = await fetch(url.toString(), { method: "GET", headers: {} });
+ if (response.status !== 200) {
+ throw new Error(`Unable to fetch token from ${url.toString()} status code ${response.status}`);
+ }
+ const body = await response.json();
+ return { token: body.token, expires_in: body.expires_in };
+ }
+ async token(authenticateStr) {
+ const wwwAuthenticate = parseAuthenticateStr(authenticateStr);
+ const cacheKey = await this.authenticateCacheKey(wwwAuthenticate);
+ const cachedToken = await this.tokenFromCache(cacheKey);
+ if (cachedToken !== null) {
+ return cachedToken;
+ }
+ const token = await this.fetchToken(wwwAuthenticate);
+ await this.tokenToCache(cacheKey, token);
+ return token;
+ }
+ };
+
+ // src/backend.ts
+ var Backend = class {
+ host;
+ tokenProvider;
+ constructor(host, tokenProvider) {
+ this.host = host;
+ this.tokenProvider = tokenProvider;
+ }
+ async proxy(pathname, args) {
+ const url = new URL(this.host);
+ url.pathname = pathname;
+ const response = await fetch(url.toString(), { method: "GET", headers: args.headers, redirect: "follow" });
+ if (this.tokenProvider === void 0) {
+ return response;
+ }
+ if (response.status !== 401) {
+ return response;
+ }
+ const authenticateStr = response.headers.get("Www-Authenticate");
+ if (authenticateStr === null || this.tokenProvider === void 0) {
+ return response;
+ }
+ const token = await this.tokenProvider.token(authenticateStr);
+ const authenticatedHeaders = new Headers(args.headers);
+ authenticatedHeaders.append("Authorization", `Bearer ${token.token}`);
+ return await fetch(url.toString(), { method: "GET", headers: authenticatedHeaders, redirect: "follow" });
+ }
+ };
+
+ // src/handler.ts
+ function getHomePageHtml() {
+ return `
+
+
+ CZL Docker\u955C\u50CF\u670D\u52A1(\u4EC5\u5185\u90E8\u7528)
+
+
+
+
+
\u5FEB\u6377\u547D\u4EE4
+
+ \u63D0\u793A\uFF0C\u652F\u6301docker.io, ghcr,quay,k8sgcr,gcr, \u975Edocker.io\u9700\u52A0\u4E0A\u57DF\u540D\u524D\u7F00
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \r\n \r\n \r\n `;\r\n}\r\n\r\nimport { TokenProvider } from './token'\r\nimport { Backend } from './backend'\r\n\r\nconst PROXY_HEADER_ALLOW_LIST: string[] = [\"accept\", \"user-agent\", \"accept-encoding\"]\r\n\r\nconst validActionNames = new Set([\"manifests\", \"blobs\", \"tags\", \"referrers\"])\r\n\r\nconst ORG_NAME_BACKEND:{ [key: string]: string; } = {\r\n \"gcr\": \"https://gcr.io\",\r\n \"k8sgcr\": \"https://k8s.gcr.io\",\r\n \"quay\": \"https://quay.io\",\r\n \"ghcr\": \"https://ghcr.io\"\r\n}\r\n\r\nconst DEFAULT_BACKEND_HOST: string = \"https://registry-1.docker.io\"\r\n\r\nexport async function handleRequest(request: Request): Promise {\r\n const url = new URL(request.url)\r\n\r\n if (url.pathname === '/') {\r\n return new Response(getHomePageHtml(), {\r\n headers: { 'content-type': 'text/html;charset=UTF-8' },\r\n })\r\n }\r\n\r\n return handleRegistryRequest(request)\r\n}\r\n\r\nfunction copyProxyHeaders(inputHeaders: Headers) : Headers {\r\n const headers = new Headers;\r\n for(const pair of inputHeaders.entries()) {\r\n if (PROXY_HEADER_ALLOW_LIST.includes(pair[0].toLowerCase())) {\r\n headers.append(pair[0], pair[1])\r\n }\r\n }\r\n return headers;\r\n}\r\n\r\nfunction orgNameFromPath(pathname: string): string|null {\r\n const splitedPath: string[] = pathname.split(\"/\", 3)\r\n if (splitedPath.length === 3 && splitedPath[0] === \"\" && splitedPath[1] === \"v2\") {\r\n return splitedPath[2].toLowerCase()\r\n }\r\n return null\r\n}\r\n\r\nfunction hostByOrgName(orgName: string|null): string {\r\n if (orgName !== null && orgName in ORG_NAME_BACKEND) {\r\n return ORG_NAME_BACKEND[orgName]\r\n }\r\n return DEFAULT_BACKEND_HOST\r\n}\r\n\r\nfunction rewritePath(orgName: string | null, pathname: string): string {\r\n let splitedPath = pathname.split(\"/\");\r\n\r\n // /v2/repo/manifests/xxx -> /v2/library/repo/manifests/xxx\r\n // /v2/repo/blobs/xxx -> /v2/library/repo/blobs/xxx\r\n if (orgName === null && splitedPath.length === 5 && validActionNames.has(splitedPath[3])) {\r\n splitedPath = [splitedPath[0], splitedPath[1], \"library\", splitedPath[2], splitedPath[3], splitedPath[4]]\r\n }\r\n\r\n if (orgName === null || !(orgName in ORG_NAME_BACKEND)) {\r\n return pathname\r\n }\r\n \r\n const cleanSplitedPath = splitedPath.filter(function(value: string, index: number) {\r\n return value !== orgName || index !== 2;\r\n })\r\n return cleanSplitedPath.join(\"/\")\r\n}\r\n\r\nasync function handleRegistryRequest(request: Request): Promise {\r\n const reqURL = new URL(request.url)\r\n const orgName = orgNameFromPath(reqURL.pathname)\r\n const pathname = rewritePath(orgName, reqURL.pathname)\r\n const host = hostByOrgName(orgName)\r\n const tokenProvider = new TokenProvider()\r\n const backend = new Backend(host, tokenProvider)\r\n const headers = copyProxyHeaders(request.headers)\r\n return backend.proxy(pathname, {headers: request.headers})\r\n}\r\n", "import { handleRequest } from './handler'\r\n\r\ndeclare global {\r\n const HAMMAL_CACHE: KVNamespace\r\n}\r\n\r\naddEventListener('fetch', (event) => {\r\n event.respondWith(handleRequest(event.request))\r\n})\r\n"],
+ "mappings": "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",
+ "names": ["ctx"]
+}
diff --git a/README.md b/README.md
index 3102c64..59e7a3f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,37 @@
-# hammal
+# Docker-Image
-Hammal 是运行于 cloudflare workers 上的 Docker 镜像加速工具,用于解决获取 Docker 官方镜像无法正常访问的问题。
+运行于 cloudflare workers 上的 Docker 镜像加速工具,用于解决获取 Docker 官方镜像无法正常访问的问题。
-文档: https://singee.atlassian.net/wiki/spaces/MAIN/pages/5079084/Cloudflare+Workers+Docker
+修改自:[https://github.com/tomwei7/hammal](https://github.com/tomwei7/hammal)
+
+## 使用说明
+
+### Fork & Clone
+
+首先 fork 仓库 [Docker-Image](https://github.com/woodchen/docker-image) ,并克隆到本地
+
+> 可以的话顺便给个 Star😂
+
+使用 `pnpm install` 安装依赖
+
+### 创建 Workers 项目
+
+进入 [Cloudflare Dashboard](https://dash.cloudflare.com/ "https://dash.cloudflare.com/") 创建一个新的 Workers 项目,给他一个命名(例如 `docker-image`)
+
+复制 `wrangler.toml.sample` 文件改名 `wrangler.toml` 并修改其 `name` 和 `account_id`
+
+account\_id 可以通过 `npx wrangler whoami` 获得,也可以从 CF Workers Dashboard 右侧获得
+
+### 创建 cache 缓存 kv
+
+在克隆好的项目目录下执行 `npx wrangler kv:namespace create hammal_cache` 来创建缓存 kv,记录下来输出的 id,填写到 `wrangler.toml` 文件中
+
+### Deploy
+
+在克隆好的项目目录下执行 `pnpm run deploy` 来部署项目
+
+进入你的 Workers 脚本的 dashboard,为它绑定一个自定义域名(必要,因为默认的 `workers.dev` 域名被墙了)
+
+### 访问
+
+直接访问自己绑定的域名就知道怎么用了
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e69de29
diff --git a/src/handler.ts b/src/handler.ts
index dba7728..8c616c9 100644
--- a/src/handler.ts
+++ b/src/handler.ts
@@ -1,3 +1,160 @@
+function getHomePageHtml(): string {
+ return `
+
+
+ CZL Docker镜像服务(仅内部用)
+
+
+
+
+
快捷命令
+
+ 提示,支持docker.io, ghcr,quay,k8sgcr,gcr, 非docker.io需加上域名前缀
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+}
+
import { TokenProvider } from './token'
import { Backend } from './backend'
@@ -5,40 +162,49 @@ const PROXY_HEADER_ALLOW_LIST: string[] = ["accept", "user-agent", "accept-encod
const validActionNames = new Set(["manifests", "blobs", "tags", "referrers"])
-// const ORG_NAME_BACKEND:{ [key: string]: string; } = {
-// "gcr": "https://gcr.io",
-// "k8sgcr": "https://k8s.gcr.io",
-// "quay": "https://quay.io",
-// }
+const ORG_NAME_BACKEND:{ [key: string]: string; } = {
+ "gcr": "https://gcr.io",
+ "k8sgcr": "https://k8s.gcr.io",
+ "quay": "https://quay.io",
+ "ghcr": "https://ghcr.io"
+}
const DEFAULT_BACKEND_HOST: string = "https://registry-1.docker.io"
export async function handleRequest(request: Request): Promise {
+ const url = new URL(request.url)
+
+ if (url.pathname === '/') {
+ return new Response(getHomePageHtml(), {
+ headers: { 'content-type': 'text/html;charset=UTF-8' },
+ })
+ }
+
return handleRegistryRequest(request)
}
function copyProxyHeaders(inputHeaders: Headers) : Headers {
const headers = new Headers;
for(const pair of inputHeaders.entries()) {
- if (pair[0].toLowerCase() in PROXY_HEADER_ALLOW_LIST) {
+ if (PROXY_HEADER_ALLOW_LIST.includes(pair[0].toLowerCase())) {
headers.append(pair[0], pair[1])
}
}
- return headers
+ return headers;
}
function orgNameFromPath(pathname: string): string|null {
- // const splitedPath: string[] = pathname.split("/", 3)
- // if (splitedPath.length === 3 && splitedPath[0] === "" && splitedPath[1] === "v2") {
- // return splitedPath[2].toLowerCase()
- // }
+ const splitedPath: string[] = pathname.split("/", 3)
+ if (splitedPath.length === 3 && splitedPath[0] === "" && splitedPath[1] === "v2") {
+ return splitedPath[2].toLowerCase()
+ }
return null
}
function hostByOrgName(orgName: string|null): string {
- // if (orgName !== null && orgName in ORG_NAME_BACKEND) {
- // return ORG_NAME_BACKEND[orgName]
- // }
+ if (orgName !== null && orgName in ORG_NAME_BACKEND) {
+ return ORG_NAME_BACKEND[orgName]
+ }
return DEFAULT_BACKEND_HOST
}
@@ -51,16 +217,14 @@ function rewritePath(orgName: string | null, pathname: string): string {
splitedPath = [splitedPath[0], splitedPath[1], "library", splitedPath[2], splitedPath[3], splitedPath[4]]
}
- return splitedPath.join("/")
-
- // if (orgName === null || !(orgName in ORG_NAME_BACKEND)) {
- // return pathname
- // }
- //
- // const cleanSplitedPath = splitedPath.filter(function(value: string, index: number) {
- // return value !== orgName || index !== 2;
- // })
- // return cleanSplitedPath.join("/")
+ if (orgName === null || !(orgName in ORG_NAME_BACKEND)) {
+ return pathname
+ }
+
+ const cleanSplitedPath = splitedPath.filter(function(value: string, index: number) {
+ return value !== orgName || index !== 2;
+ })
+ return cleanSplitedPath.join("/")
}
async function handleRegistryRequest(request: Request): Promise {