fix: rewrite all github subdomains (codeload, objects, avatars, etc.)
Build and Push to GHCR / build-and-push (push) Has been cancelled
Build and Push to GHCR / build-and-push (push) Has been cancelled
- Add isGitHubURL helper to detect github.com and all its subdomains - rewriteURL now proxies absolute GitHub URLs, not just relative paths - Injected script shares a unified domain list between rw (links) and rfw (fetch/XHR), covering codeload.github.com, objects, avatars, camo, user-images, etc. - Click/form handlers now use rw() directly so absolute GitHub URLs are also intercepted via [HAPI](https://hapi.run) Co-Authored-By: HAPI <[email protected]>
This commit is contained in:
+41
-12
@@ -141,19 +141,40 @@ func NewGitHubProxy() http.Handler {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var githubHosts = []string{
|
||||||
|
"github.com",
|
||||||
|
"www.github.com",
|
||||||
|
"raw.githubusercontent.com",
|
||||||
|
"api.github.com",
|
||||||
|
"codeload.github.com",
|
||||||
|
"objects.githubusercontent.com",
|
||||||
|
"user-images.githubusercontent.com",
|
||||||
|
"camo.githubusercontent.com",
|
||||||
|
"avatars.githubusercontent.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGitHubURL(u string) bool {
|
||||||
|
for _, h := range githubHosts {
|
||||||
|
if strings.HasPrefix(u, "https://"+h+"/") || strings.HasPrefix(u, "http://"+h+"/") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// rewriteURL 重写 URL,在前面加上 token 前缀
|
// rewriteURL 重写 URL,在前面加上 token 前缀
|
||||||
func rewriteURL(u string, prefix string) string {
|
func rewriteURL(u string, prefix string) string {
|
||||||
if u == "" || prefix == "" {
|
if u == "" || prefix == "" {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
// 已经是完整 URL(带 scheme)
|
|
||||||
if strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") {
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
// 已经是带前缀的路径
|
// 已经是带前缀的路径
|
||||||
if strings.HasPrefix(u, prefix+"/") || u == prefix {
|
if strings.HasPrefix(u, prefix+"/") || u == prefix {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
// GitHub 相关的绝对 URL,添加前缀代理
|
||||||
|
if isGitHubURL(u) {
|
||||||
|
return prefix + "/" + u
|
||||||
|
}
|
||||||
// 以 / 开头的绝对路径,加上前缀
|
// 以 / 开头的绝对路径,加上前缀
|
||||||
if strings.HasPrefix(u, "/") {
|
if strings.HasPrefix(u, "/") {
|
||||||
return prefix + u
|
return prefix + u
|
||||||
@@ -170,7 +191,14 @@ func injectTokenPrefixScript(body []byte, prefix string) []byte {
|
|||||||
`(function(){` +
|
`(function(){` +
|
||||||
`var p='` + prefix + `';` +
|
`var p='` + prefix + `';` +
|
||||||
`if(typeof crypto!=='undefined'&&!crypto.randomUUID){crypto.randomUUID=function(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c==='x'?r:(r&0x3|0x8);return v.toString(16);});};}` +
|
`if(typeof crypto!=='undefined'&&!crypto.randomUUID){crypto.randomUUID=function(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c==='x'?r:(r&0x3|0x8);return v.toString(16);});};}` +
|
||||||
`function rw(v){return v&&v.startsWith('/')&&!v.startsWith(p+'/')&&v!==p?p+v:v};` +
|
`var gh=['https://github.com/','https://www.github.com/','https://raw.githubusercontent.com/','https://api.github.com/','https://codeload.github.com/','https://objects.githubusercontent.com/','https://user-images.githubusercontent.com/','https://camo.githubusercontent.com/','https://avatars.githubusercontent.com/','http://github.com/','http://www.github.com/','http://raw.githubusercontent.com/','http://api.github.com/','http://codeload.github.com/','http://objects.githubusercontent.com/','http://user-images.githubusercontent.com/','http://camo.githubusercontent.com/','http://avatars.githubusercontent.com/','wss://github.com/','wss://raw.githubusercontent.com/','wss://api.github.com/'];` +
|
||||||
|
`function rw(v){` +
|
||||||
|
`if(!v||v===p)return v;` +
|
||||||
|
`if(v.startsWith(p+'/'))return v;` +
|
||||||
|
`for(var i=0;i<gh.length;i++){if(v.startsWith(gh[i]))return p+'/'+v;}` +
|
||||||
|
`if(v.startsWith('/'))return p+v;` +
|
||||||
|
`return v;` +
|
||||||
|
`}` +
|
||||||
`function rfw(u){` +
|
`function rfw(u){` +
|
||||||
`if(typeof u!=='string'){` +
|
`if(typeof u!=='string'){` +
|
||||||
`if(u&&typeof u==='object'){` +
|
`if(u&&typeof u==='object'){` +
|
||||||
@@ -180,8 +208,7 @@ func injectTokenPrefixScript(body []byte, prefix string) []byte {
|
|||||||
`return u;` +
|
`return u;` +
|
||||||
`}` +
|
`}` +
|
||||||
`if(u.startsWith(p+'/')||u===p)return u;` +
|
`if(u.startsWith(p+'/')||u===p)return u;` +
|
||||||
`var a=['https://github.com/','https://raw.githubusercontent.com/','https://api.github.com/','wss://github.com/','wss://raw.githubusercontent.com/','wss://api.github.com/'];` +
|
`for(var i=0;i<gh.length;i++){if(u.startsWith(gh[i]))return p+'/'+u;}` +
|
||||||
`for(var i=0;i<a.length;i++){if(u.startsWith(a[i]))return p+'/'+u;}` +
|
|
||||||
`if(u.startsWith('/'))return p+u;` +
|
`if(u.startsWith('/'))return p+u;` +
|
||||||
`return u;` +
|
`return u;` +
|
||||||
`}` +
|
`}` +
|
||||||
@@ -192,7 +219,7 @@ func injectTokenPrefixScript(body []byte, prefix string) []byte {
|
|||||||
`function fix(root){` +
|
`function fix(root){` +
|
||||||
`root.querySelectorAll&&root.querySelectorAll('a[href]').forEach(function(a){a.href=rw(a.getAttribute('href'))});` +
|
`root.querySelectorAll&&root.querySelectorAll('a[href]').forEach(function(a){a.href=rw(a.getAttribute('href'))});` +
|
||||||
`root.querySelectorAll&&root.querySelectorAll('form[action]').forEach(function(f){f.action=rw(f.getAttribute('action'))});` +
|
`root.querySelectorAll&&root.querySelectorAll('form[action]').forEach(function(f){f.action=rw(f.getAttribute('action'))});` +
|
||||||
`root.querySelectorAll&&root.querySelectorAll('[src]').forEach(function(el){var s=el.getAttribute('src');if(s&&s.startsWith('/')&&!s.startsWith(p+'/'))el.setAttribute('src',p+s)});` +
|
`root.querySelectorAll&&root.querySelectorAll('[src]').forEach(function(el){var s=el.getAttribute('src');if(s){var rs=rw(s);if(rs!==s)el.setAttribute('src',rs)}});` +
|
||||||
`}` +
|
`}` +
|
||||||
`fix(document);` +
|
`fix(document);` +
|
||||||
`if(window.MutationObserver){` +
|
`if(window.MutationObserver){` +
|
||||||
@@ -202,17 +229,19 @@ func injectTokenPrefixScript(body []byte, prefix string) []byte {
|
|||||||
`var a=e.target.closest('a');` +
|
`var a=e.target.closest('a');` +
|
||||||
`if(!a)return;` +
|
`if(!a)return;` +
|
||||||
`var h=a.getAttribute('href');` +
|
`var h=a.getAttribute('href');` +
|
||||||
`if(h&&h.startsWith('/')&&!h.startsWith(p+'/')&&h!==p){` +
|
`var rh=rw(h);` +
|
||||||
|
`if(rh!==h){` +
|
||||||
`e.preventDefault();` +
|
`e.preventDefault();` +
|
||||||
`location.href=p+h;` +
|
`location.href=rh;` +
|
||||||
`}` +
|
`}` +
|
||||||
`},true);` +
|
`},true);` +
|
||||||
`document.addEventListener('submit',function(e){` +
|
`document.addEventListener('submit',function(e){` +
|
||||||
`var f=e.target.closest('form');` +
|
`var f=e.target.closest('form');` +
|
||||||
`if(!f)return;` +
|
`if(!f)return;` +
|
||||||
`var h=f.getAttribute('action');` +
|
`var h=f.getAttribute('action');` +
|
||||||
`if(h&&h.startsWith('/')&&!h.startsWith(p+'/')&&h!==p){` +
|
`var rh=rw(h);` +
|
||||||
`f.setAttribute('action',p+h);` +
|
`if(rh!==h){` +
|
||||||
|
`f.setAttribute('action',rh);` +
|
||||||
`}` +
|
`}` +
|
||||||
`},true);` +
|
`},true);` +
|
||||||
`})();` +
|
`})();` +
|
||||||
|
|||||||
Reference in New Issue
Block a user