GitHub 图床 + Cloudflare 加速 部署

1. 问题背景:GitHub 图床的局限性

  • GitHub 图床免费且稳定,但其图片外链 raw.githubusercontent.com 经常在国内访问缓慢,甚至被墙,影响图片加载速度。
  • 解决方案:利用 Cloudflare CDN 对 GitHub 图床的外链进行加速,将图片通过 Cloudflare 的域名访问,从而绕开网络限制。

2. 创建 GitHub 图床仓库

  • 登录 GitHub
  • 创建一个新的存储仓库

01

输入存储库名称,现在建立私库(不公开)(例如 hans-img

image-20241123164709435

3. GitHub 生成Personal access token(个人令牌)

  • 点击右上角用户头像,选择 Settings(设置)
  • 在页面左侧菜单栏最后,选择 Developer settings(开发人员设置)
  • 然后点击 Personal access tokens(个人[访问令牌),选择 Token(classic)
  • 点击 Generate new token 开始创建一个新的令牌,注意一定要选择 classic 方式

image-20241123170701295

  • 输入个人令牌名称(自定义),Expiration选择No expiratio(永久)然后repo全部打勾,其他保持默认

image-20241123171129480

保存生成的tokens

1
注:要保存个人令牌,页面关闭后就无法查看!

image-20241123171417366

  1. 上传图片到仓库,可以通过 GitHub 的 Web 界面直接拖拽上传。
  2. 获取图片外链:上传后点击图片,右键复制 raw.githubusercontent.com 的 URL,即为图片的外链地址。

4. Cloudflare 加速 GitHub 图床

  • 登录 Cloudflare
  • 左侧菜单栏找到Workers和Pages
  • 创建一个新的Workers,输入项目名称,然后部署
  • 打开Workers项目,找到右上方 编辑代码
  • 清空编辑器原来代码,复制粘贴下面代码
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
// Website you intended to retrieve for users.
const upstream = "raw.githubusercontent.com";

// Custom pathname for the upstream website.
// (1) 填写代理的路径,格式为 /<用户>/<仓库名>/<分支>
const upstream_path = "/hansvlss/PicGo-img/master";

// github personal access token.
// (2) 填写github令牌
const github_token = "_";

// Website you intended to retrieve for users using mobile devices.
const upstream_mobile = upstream;

// Countries and regions where you wish to suspend your service.
const blocked_region = [];

// IP addresses which you wish to block from using your service.
const blocked_ip_address = ["0.0.0.0", "127.0.0.1"];

// Whether to use HTTPS protocol for upstream address.
const https = true;

// Whether to disable cache.
const disable_cache = false;

// Replace texts.
const replace_dict = {
$upstream: "$custom_domain",
};

addEventListener("fetch", (event) => {
event.respondWith(fetchAndApply(event.request));
});

async function fetchAndApply(request) {
const region = request.headers.get("cf-ipcountry")?.toUpperCase();
const ip_address = request.headers.get("cf-connecting-ip");
const user_agent = request.headers.get("user-agent");

let response = null;
let url = new URL(request.url);
let url_hostname = url.hostname;

if (https == true) {
url.protocol = "https:";
} else {
url.protocol = "http:";
}

if (await device_status(user_agent)) {
var upstream_domain = upstream;
} else {
var upstream_domain = upstream_mobile;
}

url.host = upstream_domain;
if (url.pathname == "/") {
url.pathname = upstream_path;
} else {
url.pathname = upstream_path + url.pathname;
}

if (blocked_region.includes(region)) {
response = new Response(
"Access denied: WorkersProxy is not available in your region yet.",
{
status: 403,
}
);
} else if (blocked_ip_address.includes(ip_address)) {
response = new Response(
"Access denied: Your IP address is blocked by WorkersProxy.",
{
status: 403,
}
);
} else {
let method = request.method;
let request_headers = request.headers;
let new_request_headers = new Headers(request_headers);

new_request_headers.set("Host", upstream_domain);
new_request_headers.set("Referer", url.protocol + "//" + url_hostname);
new_request_headers.set("Authorization", "token " + github_token);

let original_response = await fetch(url.href, {
method: method,
headers: new_request_headers,
body: request.body,
});

connection_upgrade = new_request_headers.get("Upgrade");
if (connection_upgrade && connection_upgrade.toLowerCase() == "websocket") {
return original_response;
}

let original_response_clone = original_response.clone();
let original_text = null;
let response_headers = original_response.headers;
let new_response_headers = new Headers(response_headers);
let status = original_response.status;

if (disable_cache) {
new_response_headers.set("Cache-Control", "no-store");
} else {
new_response_headers.set("Cache-Control", "max-age=43200000");
}

new_response_headers.set("access-control-allow-origin", "*");
new_response_headers.set("access-control-allow-credentials", true);
new_response_headers.delete("content-security-policy");
new_response_headers.delete("content-security-policy-report-only");
new_response_headers.delete("clear-site-data");

if (new_response_headers.get("x-pjax-url")) {
new_response_headers.set(
"x-pjax-url",
response_headers
.get("x-pjax-url")
.replace("//" + upstream_domain, "//" + url_hostname)
);
}

const content_type = new_response_headers.get("content-type");
if (
content_type != null &&
content_type.includes("text/html") &&
content_type.includes("UTF-8")
) {
original_text = await replace_response_text(
original_response_clone,
upstream_domain,
url_hostname
);
} else {
original_text = original_response_clone.body;
}

response = new Response(original_text, {
status,
headers: new_response_headers,
});
}
return response;
}

async function replace_response_text(response, upstream_domain, host_name) {
let text = await response.text();

var i, j;
for (i in replace_dict) {
j = replace_dict[i];
if (i == "$upstream") {
i = upstream_domain;
} else if (i == "$custom_domain") {
i = host_name;
}

if (j == "$upstream") {
j = upstream_domain;
} else if (j == "$custom_domain") {
j = host_name;
}

let re = new RegExp(i, "g");
text = text.replace(re, j);
}
return text;
}

async function device_status(user_agent_info) {
var agents = [
"Android",
"iPhone",
"SymbianOS",
"Windows Phone",
"iPad",
"iPod",
];
var flag = true;
for (var v = 0; v < agents.length; v++) {
if (user_agent_info.indexOf(agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}

修改第6行第10行,替换你自己的信息,然后点击右上角部署

1
注:const upstream_path填写GitHub仓库路径,格式为 /<用户>/<仓库名>/<分支>;const github_token填许GitHub创建的个人令牌;

image-20241123174028171

添加你自己的域名到 Cloudflare

1
点击设置` `找到域和路由` `点击添加` `输入二级域名

注:输入托管到Cloudflare的二级域名(域名前面添加一个名称就变成二级域名);

image-20241123175639086

5. PicGo 配置

  • 打开PicGo,点击图床设置,找到GitHub

  • 图床设置GitHub

    • 图床配置名:自定义,

    • 仓库名:GitHub账号名/仓库名称

    • 设定Token:填写GitHub个人令牌;

    • 自定义域:https://+Workers绑定的二级域名;

      1
      注:可以参考我的模版,替换你的信息,点击确定,然后设为默认图床;

image-20241123201201930

点击上传区,图片上传确认图床名称,然后通过拖拽图片/选择图片/剪贴板图片上传即可

image-20241123192359420

图床部署完成GitHub存储库验证

1
注:由于PicGo存储路径没有设置,默认上传到根目录,可设置目录可以更好分类管理;

image-20241123192809388