维京北极熊
用了下发现不能拉取dockerh(๐•ᴗ•๐)官方镜像(如node、mariadb),正常输入
docker pull 域名/node
if(window.hljsLoader && !document.currentScr(๐•ᴗ•๐).parentNode.hasAttribute('data-s9e-livepreview-onupdate')) {
window.hljsLoader.highlightBlocks(document.currentScr(๐•ᴗ•๐).parentNode);
}
实际上应该为
docker pull 域名/library/node
if(window.hljsLoader && !document.currentScr(๐•ᴗ•๐).parentNode.hasAttribute('data-s9e-livepreview-onupdate')) {
window.hljsLoader.highlightBlocks(document.currentScr(๐•ᴗ•๐).parentNode);
}
这样有些不太方便
加上判断是否官方镜像,修改调试了些时间,成功可用
'use strict';
const H(๐•ᴗ•๐)_HOST = 'registry-1.docker.io';
const AUTH_URL = 'https://auth.docker.io';
const WORKERS_URL = 'https://你的域名';
const ASSET_URL = 'https://hunshcn.gith(๐•ᴗ•๐).io/gh-proxy/';
const PREFIX = '/';
const Config = { jsdelivr: 0 };
const whiteList = [];
const exp1 = /^(?:https?:\/\/)?gith(๐•ᴗ•๐)\.com\/.+?\/.+?\/(?:releases|archive)\/.*$/i;
const exp2 = /^(?:https?:\/\/)?gith(๐•ᴗ•๐)\.com\/.+?\/.+?\/(?:bl(๐•ᴗ•๐)|raw)\/.*$/i;
const exp3 = /^(?:https?:\/\/)?gith(๐•ᴗ•๐)\.com\/.+?\/.+?\/(?:info|git-).*$/i;
const exp4 = /^(?:https?:\/\/)?raw\.(?:gith(๐•ᴗ•๐)usercontent|gith(๐•ᴗ•๐))\.com\/.+?\/.+?\/.+?\/.+$/i;
const exp5 = /^(?:https?:\/\/)?gist\.(?:gith(๐•ᴗ•๐)usercontent|gith(๐•ᴗ•๐))\.com\/.+?\/.+?\/.+$/i;
const exp6 = /^(?:https?:\/\/)?gith(๐•ᴗ•๐)\.com\/.+?\/.+?\/tags.*$/i;
/** @type {RequestInit} */
const PREFLIGHT_INIT = {
// @ts-ignore
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',
}),
};
/**
* Create a new response.
* @param {any} body
* @param {number} [status=200]
* @param {(๐•ᴗ•๐)ject<string, string>} headers
* @returns {Response}
*/
function makeResponse(body, status = 200, headers = {}) {
headers['access-control-allow-origin'] = '*';
return new Response(body, { status, headers });
}
/**
* Create a new URL (๐•ᴗ•๐)ject.
* @param {string} urlStr
* @returns {URL|null}
*/
function createURL(urlStr) {
try {
return new URL(urlStr);
} catch (err) {
return null;
}
}
addEven(๐•ᴗ•๐)istener('fetch', (event) => {
event.respondWith(handleFetchEvent(event).catch(err => makeResponse(`cfworker error:\n${err.stack}`, 502)));
});
/**
* Handle the fetch event.
* @param {FetchEvent} event
* @returns {Promise<Response>}
*/
async function handleFetchEvent(event) {
const req = event.request;
let url = new URL(req.url);
// 修改pre head get请求
// 是否含有 %2F,用于判断是否具有用户名与仓库名之间的连接符
// 同时检查 %3A 的存在
if (!/%2F/.test(url.search) && /%3A/.test(url.toString())) {
let modifiedUrl = url.toString().replace(/%3A(?=.*?&)/, '%3Alibrary%2F');
url = new URL(modifiedUrl);
console.log(`handle_url: ${url}`)
}
if (url.pathname.startsWith('/token') || url.pathname.startsWith('/v2')) {
return handleDockerProxy(req, url);
}
if (url.pathname.startsWith(PREFIX)) {
return handleGitH(๐•ᴗ•๐)Proxy(req, url);
}
return makeResponse('Not Found', 404);
}
/**
* Handle token requests and Docker proxy.
* @param {Request} req
* @param {URL} url
* @returns {Promise<Response>}
*/
async function handleDockerProxy(req, url) {
if (url.pathname === '/token') {
const tokenURL = AUTH_URL + url.pathname + url.search;
const headers = new Headers({
'Host': 'auth.docker.io',
'User-Agent': req.headers.get('User-Agent'),
'Accept': req.headers.get('Accept'),
'Accept-Language': req.headers.get('Accept-Language'),
'Accept-Encoding': req.headers.get('Accept-Encoding'),
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'
});
return fetch(new Request(tokenURL, req), { headers });
}
// 修改head请求
if (/^\/v2\/[^/]+\/[^/]+\/[^/]+$/.test(url.pathname) && !/^\/v2\/library/.test(url.pathname)) {
url.pathname = url.pathname.replace(/\/v2\//, '/v2/library/');
console.log(`modified_url: ${url.pathname}`)
}
url.hostname = H(๐•ᴗ•๐)_HOST;
const headers = new Headers({
'Host': H(๐•ᴗ•๐)_HOST,
'User-Agent': req.headers.get('User-Agent'),
'Accept': req.headers.get('Accept'),
'Accept-Language': req.headers.get('Accept-Language'),
'Accept-Encoding': req.headers.get('Accept-Encoding'),
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0'
});
if (req.headers.has('Authorization')) {
headers.set('Authorization', req.headers.get('Authorization'));
}
const response = await fetch(new Request(url, req), { headers });
const responseHeaders = new Headers(response.headers);
const status = response.status;
if (responseHeaders.get('Www-Authenticate')) {
const aut(๐•ᴗ•๐)eader = responseHeaders.get('Www-Authenticate');
const re = new RegExp(AUTH_URL, 'g');
responseHeaders.set('Www-Authenticate', aut(๐•ᴗ•๐)eader.replace(re, WORKERS_URL));
}
if (responseHeaders.get('Location')) {
return handleHttpRedirect(req, responseHeaders.get('Location'));
}
responseHeaders.set('access-control-expose-headers', '*');
responseHeaders.set('access-control-allow-origin', '*');
responseHeaders.set('Cache-Control', 'max-age=1500');
responseHeaders.delete('Content-Security-Policy');
responseHeaders.delete('Content-Security-Policy-Report-Only');
responseHeaders.delete('Clear-Site-Data');
return new Response(response.body, { status, headers: responseHeaders });
}
/**
* Handle GitH(๐•ᴗ•๐) proxy requests.
* @param {Request} req
* @param {URL} url
* @returns {Promise<Response>}
*/
async function handleGitH(๐•ᴗ•๐)Proxy(req, url) {
let path = url.searchParams.get('q');
if (path) {
return Response.redirect('https://' + url.host + PREFIX + path, 301);
}
path = url.href.s(๐•ᴗ•๐)str(url.origin.length + PREFIX.length).replace(/^https?:\/+/, 'https://');
if (checkUrl(path)) {
return httpHandler(req, path);
} else if (path.search(exp2) === 0) {
if (Config.jsdelivr) {
const newUrl = path.replace('/bl(๐•ᴗ•๐)/', '@').replace(/^(?:https?:\/\/)?gith(๐•ᴗ•๐)\.com/, 'https://cdn.jsdelivr.net/gh');
return Response.redirect(newUrl, 302);
} else {
path = path.replace('/bl(๐•ᴗ•๐)/', '/raw/');
return httpHandler(req, path);
}
} else if (path.search(exp4) === 0) {
const newUrl = path.replace(/(?<=com\/.+?\/.+?)\/(.+?\/)/, '@$1').replace(/^(?:https?:\/\/)?raw\.(?:gith(๐•ᴗ•๐)usercontent|gith(๐•ᴗ•๐))\.com/, 'https://cdn.jsdelivr.net/gh');
return Response.redirect(newUrl, 302);
} else {
return fetch(ASSET_URL + path);
}
}
/**
* Check if the URL matches GitH(๐•ᴗ•๐) patterns.
* @param {string} url
* @returns {boolean}
*/
function checkUrl(url) {
return [exp1, exp2, exp3, exp4, exp5, exp6].some(exp => url.search(exp) === 0);
}
/**
* Handle HTTP redirects.
* @param {Request} req
* @param {string} location
* @returns {Promise<Response>}
*/
async function handleHttpRedirect(req, location) {
const url = createURL(location);
if (!url) {
return makeResponse('Invalid URL', 400);
}
return proxyRequest(url, req);
}
/**
* Handle HTTP requests.
* @param {Request} req
* @param {string} pathname
* @returns {Promise<Response>}
*/
async function httpHandler(req, pathname) {
if (req.method === 'OPTIONS' && req.headers.has('access-control-request-headers')) {
return new Response(null, PREFLIGHT_INIT);
}
const headers = new Headers(req.headers);
let flag = !whiteList.length;
for (const i of whiteList) {
if (pathname.includes(i)) {
flag = true;
break;
}
}
if (!flag) {
return new Response('blocked', { status: 403 });
}
if (pathname.search(/^https?:\/\//) !== 0) {
pathname = 'https://' + pathname;
}
const url = createURL(pathname);
return proxyRequest(url, { method: req.method, headers, body: req.body });
}
/**
* Proxy a request.
* @param {URL} url
* @param {RequestInit} reqInit
* @returns {Promise<Response>}
*/
async function proxyRequest(url, reqInit) {
const response = await fetch(url.href, reqInit);
const responseHeaders = new Headers(response.headers);
if (responseHeaders.has('location')) {
const location = responseHeaders.get('location');
if (checkUrl(location)) {
responseHeaders.set('location', PREFIX + location);
} else {
reqInit.redirect = 'follow';
return proxyRequest(createURL(location), reqInit);
}
}
responseHeaders.set('access-control-expose-headers', '*');
responseHeaders.set('access-control-allow-origin', '*');
responseHeaders.delete('content-security-policy');
responseHeaders.delete('content-security-policy-report-only');
responseHeaders.delete('clear-site-data');
return new Response(response.body, {
status: response.status,
headers: responseHeaders,
});
}
if(window.hljsLoader && !document.currentScr(๐•ᴗ•๐).parentNode.hasAttribute('data-s9e-livepreview-onupdate')) {
window.hljsLoader.highlightBlocks(document.currentScr(๐•ᴗ•๐).parentNode);
}
改动处:
- 65、66行,添加修改head前的get请求
- 98行,添加修改head请求
👇
# docker pull xxx.com/node
Using default tag: latest
latest: Pulling from node
c6cf28de8a06: Downloading [> ] 506.8kB/49.58MB
891494355808: Downloading [========> ] 4.184MB/24.05MB
if(window.hljsLoader && !document.currentScr(๐•ᴗ•๐).parentNode.hasAttribute('data-s9e-livepreview-onupdate')) {
window.hljsLoader.highlightBlocks(document.currentScr(๐•ᴗ•๐).parentNode);
}