抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

简介

利用 Cloudflare 代理访问 GitHub 地址,同理可应用于其他网址。

准备

  • Cloudflare 账号
  • 域名(自行注册)

实现方法

  1. 登录 Cloudflare,把你的域名添加到 Cloudflare。
  2. 处理域名的 DNS
  3. 新增 Woker worker 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
"use strict";

/**
* static files (404.html, sw.js, conf.js)
*/
const ASSET_URL = "https://域名/";
// 前缀,如果自定义路由为example.com/gh/*,将PREFIX改为 '/gh/',注意,少一个杠都会错!
const PREFIX = "/";
// 分支文件使用jsDelivr镜像的开关,0为关闭,默认关闭
const Config = {
jsdelivr: 0,
};

const whiteList = []; // 白名单,路径里面有包含字符的才会通过,e.g. ['/username/']

/** @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",
}),
};

const exp1 =
/^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:releases|archive)\/.*$/i;
const exp2 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:blob|raw)\/.*$/i;
const exp3 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:info|git-).*$/i;
const exp4 =
/^(?:https?:\/\/)?raw\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+?\/.+$/i;
const exp5 =
/^(?:https?:\/\/)?gist\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+$/i;
const exp6 = /^(?:https?:\/\/)?github\.com\/.+?\/.+?\/tags.*$/i;

/**
* @param {any} body
* @param {number} status
* @param {Object<string, string>} headers
*/
function makeRes(body, status = 200, headers = {}) {
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);
});

function checkUrl(u) {
for (let i of [exp1, exp2, exp3, exp4, exp5, exp6]) {
if (u.search(i) === 0) {
return true;
}
}
return false;
}

/**
* @param {FetchEvent} e
*/
async function fetchHandler(e) {
const req = e.request;
const urlStr = req.url;
const urlObj = new URL(urlStr);
let path = urlObj.searchParams.get("q");
if (path) {
return Response.redirect("https://" + urlObj.host + PREFIX + path, 301);
}
// cfworker 会把路径中的 `//` 合并成 `/`
path = urlObj.href
.substr(urlObj.origin.length + PREFIX.length)
.replace(/^https?:\/+/, "https://");
if (
path.search(exp1) === 0 ||
path.search(exp5) === 0 ||
path.search(exp6) === 0 ||
path.search(exp3) === 0 ||
path.search(exp4) === 0
) {
return httpHandler(req, path);
} else if (path.search(exp2) === 0) {
if (Config.jsdelivr) {
const newUrl = path
.replace("/blob/", "@")
.replace(/^(?:https?:\/\/)?github\.com/, "https://cdn.jsdelivr.net/gh");
return Response.redirect(newUrl, 302);
} else {
path = path.replace("/blob/", "/raw/");
return httpHandler(req, path);
}
} else if (path.search(exp4) === 0) {
const newUrl = path
.replace(/(?<=com\/.+?\/.+?)\/(.+?\/)/, "@$1")
.replace(
/^(?:https?:\/\/)?raw\.(?:githubusercontent|github)\.com/,
"https://cdn.jsdelivr.net/gh"
);
return Response.redirect(newUrl, 302);
} else {
return fetch(ASSET_URL + path);
}
}

/**
* @param {Request} req
* @param {string} pathname
*/
function httpHandler(req, pathname) {
const reqHdrRaw = req.headers;

// preflight
if (
req.method === "OPTIONS" &&
reqHdrRaw.has("access-control-request-headers")
) {
return new Response(null, PREFLIGHT_INIT);
}

const reqHdrNew = new Headers(reqHdrRaw);

let urlStr = pathname;
let flag = !Boolean(whiteList.length);
for (let i of whiteList) {
if (urlStr.includes(i)) {
flag = true;
break;
}
}
if (!flag) {
return new Response("blocked", { status: 403 });
}
if (urlStr.startsWith("github")) {
urlStr = "https://" + urlStr;
}
const urlObj = newUrl(urlStr);

/** @type {RequestInit} */
const reqInit = {
method: req.method,
headers: reqHdrNew,
redirect: "manual",
body: req.body,
};
return proxy(urlObj, reqInit);
}

/**
*
* @param {URL} urlObj
* @param {RequestInit} reqInit
*/
async function proxy(urlObj, reqInit) {
const res = await fetch(urlObj.href, reqInit);
const resHdrOld = res.headers;
const resHdrNew = new Headers(resHdrOld);

const status = res.status;

if (resHdrNew.has("location")) {
let _location = resHdrNew.get("location");
if (checkUrl(_location)) resHdrNew.set("location", PREFIX + _location);
else {
reqInit.redirect = "follow";
return proxy(newUrl(_location), reqInit);
}
}
resHdrNew.set("access-control-expose-headers", "*");
// resHdrNew.set('access-control-allow-origin', '*')

resHdrNew.delete("content-security-policy");
resHdrNew.delete("content-security-policy-report-only");
resHdrNew.delete("clear-site-data");

return new Response(res.body, {
status,
headers: resHdrNew,
});
}
  1. 设置路由 例如我的路由为

所有步骤完成后基本上就可以根据你的域名访问 GitHub 托管的博客了,如果没有效果的话可能要等 Cloudflare 域名激活或者等一会儿 worker 生效

GitHub 图床

GitHub 图床也可以用这个 worker 代码来代理,新增一个 worker,注意 github 图片的代理地址要写https://raw.githubusercontent.com/GitHub用户名/图床仓库名/分支名/,根据个人情况进行修改。可以在域名下添加一个路由,我是用的是img.busyo.link/*进行路由,然后添加 img 的 DNS,访问图片只要使用https://img.busyo.link/仓库中的图片路径即可。

例:

1
2
3
4
5
6
7
8
9
10
//代理地址
https://raw.githubusercontent.com/UserName/PictureReposity/main/

//仓库结构
PictureReposity
|- picture
|-- test.png

//访问地址
https://domain.com/picture/test.png

评论