4.1.7-rc.0
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# 更新日志
|
||||
|
||||
4.1.7-rc.0 - 2025-07-20
|
||||
---
|
||||
- PRE-RELEASE: v4.1.7-rc.0是v4.1.7预发布版本,请勿在生产环境中使用;
|
||||
- CHANGE: 更新相关依赖
|
||||
- CHANGE: 改进代码结构, 完善处理
|
||||
|
||||
4.1.6 - 2025-07-07
|
||||
---
|
||||
- CHANGE: 更新[Touka框架](https://github.com/infinite-iroha/touka)版本到`v0.2.9`, 提升`io`相关方式的性能并降低分配
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.1.6-rc.0
|
||||
4.1.7-rc.0
|
||||
@@ -60,12 +60,14 @@ type HttpcConfig struct {
|
||||
[gitclone]
|
||||
mode = "bypass" # bypass / cache
|
||||
smartGitAddr = "http://127.0.0.1:8080"
|
||||
//cacheTimeout = 10
|
||||
ForceH2C = true
|
||||
*/
|
||||
type GitCloneConfig struct {
|
||||
Mode string `toml:"mode"`
|
||||
SmartGitAddr string `toml:"smartGitAddr"`
|
||||
ForceH2C bool `toml:"ForceH2C"`
|
||||
//CacheTimeout int `toml:"cacheTimeout"`
|
||||
ForceH2C bool `toml:"ForceH2C"`
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -175,10 +177,11 @@ user1 = "testpass"
|
||||
test = "test123"
|
||||
*/
|
||||
type DockerConfig struct {
|
||||
Enabled bool `toml:"enabled"`
|
||||
Target string `toml:"target"`
|
||||
Auth bool `toml:"auth"`
|
||||
Credentials map[string]string `toml:"credentials"`
|
||||
Enabled bool `toml:"enabled"`
|
||||
Target string `toml:"target"`
|
||||
Auth bool `toml:"auth"`
|
||||
Credentials map[string]string `toml:"credentials"`
|
||||
AuthPassThrough bool `toml:"authPassThrough"`
|
||||
}
|
||||
|
||||
// LoadConfig 从 TOML 配置文件加载配置
|
||||
|
||||
10
go.mod
10
go.mod
@@ -1,11 +1,11 @@
|
||||
module ghproxy
|
||||
|
||||
go 1.24.4
|
||||
go 1.24.5
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.0
|
||||
golang.org/x/net v0.41.0
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.1
|
||||
golang.org/x/net v0.42.0
|
||||
golang.org/x/time v0.12.0
|
||||
)
|
||||
|
||||
@@ -16,12 +16,12 @@ require (
|
||||
github.com/fenthope/reco v0.0.3
|
||||
github.com/fenthope/record v0.0.3
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/infinite-iroha/touka v0.2.9
|
||||
github.com/infinite-iroha/touka v0.3.1
|
||||
github.com/wjqserver/modembed v0.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.6 // indirect
|
||||
github.com/go-json-experiment/json v0.0.0-20250626171732-1a886bd29d1b // indirect
|
||||
github.com/go-json-experiment/json v0.0.0-20250714165856-be8212f5270d // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
)
|
||||
|
||||
16
go.sum
16
go.sum
@@ -4,8 +4,8 @@ github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.6 h1:/50VJYXd6jcu+p5BnEBDyiX0nAy
|
||||
github.com/WJQSERVER-STUDIO/go-utils/copyb v0.0.6/go.mod h1:FZ6XE+4TKy4MOfX1xWKe6Rwsg0ucYFCdNh1KLvyKTfc=
|
||||
github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2 h1:8bBkKk6E2Zr+I5szL7gyc5f0DK8N9agIJCpM1Cqw2NE=
|
||||
github.com/WJQSERVER-STUDIO/go-utils/limitreader v0.0.2/go.mod h1:yPX8xuZH+py7eLJwOYj3VVI/4/Yuy5+x8Mhq8qezcPg=
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.0 h1:G7inJ5EEsg5+BkeFiNIo/6+Mj7Ygiq85yMT3Ld7frJY=
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.0/go.mod h1:50297rvgppmgPbZEtWzTWgkomoqPREkGy9T3Y/NqN7o=
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.1 h1:/eG8aYKL3WfQILIRbG+cbzQjPkNHEPTqfGUdQS5rtI4=
|
||||
github.com/WJQSERVER-STUDIO/httpc v0.8.1/go.mod h1:mxXBf2hqbQGNHkVy/7wfU7Xi2s09MyZpbY2hyR+4uD4=
|
||||
github.com/fenthope/bauth v0.0.1 h1:+4UIQshGx3mYD4L3f2S4MLZOi5PWU7fU5GK3wsZvwzE=
|
||||
github.com/fenthope/bauth v0.0.1/go.mod h1:1fveTpgfR1p+WXQ8MXm9BfBCeNYi55j23jxCOGOvBSA=
|
||||
github.com/fenthope/ikumi v0.0.2 h1:5oaSTf/Msp7M2O3o/X20omKWEQbFhX4KV0CVF21oCdk=
|
||||
@@ -14,17 +14,17 @@ github.com/fenthope/reco v0.0.3 h1:RmnQ0D9a8PWtwOODawitTe4BztTnS9wYwrDbipISNq4=
|
||||
github.com/fenthope/reco v0.0.3/go.mod h1:mDkGLHte5udWTIcjQTxrABRcf56SSdxBOCLgrRDwI/Y=
|
||||
github.com/fenthope/record v0.0.3 h1:v5urgs5LAkLMlljAT/MjW8fWuRHXPnAraTem5ui7rm4=
|
||||
github.com/fenthope/record v0.0.3/go.mod h1:KFEkSc4TDZ3QIhP/wglD32uYVA6X1OUcripiao1DEE4=
|
||||
github.com/go-json-experiment/json v0.0.0-20250626171732-1a886bd29d1b h1:ooF9/NzXkXL3OOLRwtPuQT/D7Kx2S5w/Kl1GnMF9h2s=
|
||||
github.com/go-json-experiment/json v0.0.0-20250626171732-1a886bd29d1b/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
||||
github.com/go-json-experiment/json v0.0.0-20250714165856-be8212f5270d h1:+d6m5Bjvv0/RJct1VcOw2P5bvBOGjENmxORJYnSYDow=
|
||||
github.com/go-json-experiment/json v0.0.0-20250714165856-be8212f5270d/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/infinite-iroha/touka v0.2.9 h1:Ugu0H3Zdip/ZnDbaCXquxsWnntByCUDBONez1oZANaU=
|
||||
github.com/infinite-iroha/touka v0.2.9/go.mod h1:Cmok9Xs8yNRNEUSqiZfi3xtdO1UZYw/yP+phf+zjH2Y=
|
||||
github.com/infinite-iroha/touka v0.3.1 h1:djR9hg5MbVpT1dIz2GWo4MZ/kx3l6bJ4nrpzpvdi3uk=
|
||||
github.com/infinite-iroha/touka v0.3.1/go.mod h1:pHOYHE4AKoQ1KikHF9JYKIJ4he8um1MzgcddscjCeyg=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/wjqserver/modembed v0.0.1 h1:8ZDz7t9M5DLrUFlYgBUUmrMzxWsZPmHvOazkr/T2jEs=
|
||||
github.com/wjqserver/modembed v0.0.1/go.mod h1:sYbQJMAjSBsdYQrUsuHY380XXE1CuRh8g9yyCztTXOQ=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
|
||||
8
main.go
8
main.go
@@ -337,6 +337,7 @@ func main() {
|
||||
|
||||
r.Use(touka.Recovery()) // Recovery中间件
|
||||
r.SetLogger(logger)
|
||||
r.SetErrorHandler(proxy.UnifiedToukaErrorHandler)
|
||||
r.SetHTTPClient(httpClient)
|
||||
r.Use(record.Middleware()) // log中间件
|
||||
r.Use(viaHeader())
|
||||
@@ -367,7 +368,6 @@ func main() {
|
||||
}
|
||||
setupApi(cfg, r, version)
|
||||
setupPages(cfg, r)
|
||||
//r.RedirectTrailingSlash = false
|
||||
r.SetRedirectTrailingSlash(false)
|
||||
|
||||
r.GET("/github.com/:user/:repo/releases/*filepath", func(c *touka.Context) {
|
||||
@@ -443,12 +443,6 @@ func main() {
|
||||
proxy.GhcrWithImageRouting(cfg)(c)
|
||||
})
|
||||
|
||||
/*
|
||||
r.Any("/v2/:target/*filepath", func( c *touka.Context) {
|
||||
proxy.GhcrRouting(cfg)(c)
|
||||
})
|
||||
*/
|
||||
|
||||
r.NoRoute(func(c *touka.Context) {
|
||||
proxy.NoRouteHandler(cfg)(c)
|
||||
})
|
||||
|
||||
@@ -48,12 +48,12 @@ func GhcrWithImageRouting(cfg *config.Config) touka.HandlerFunc {
|
||||
target := ""
|
||||
|
||||
if strings.ContainsRune(reqTarget, charToFind) {
|
||||
|
||||
if reqTarget == "docker.io" {
|
||||
switch reqTarget {
|
||||
case "docker.io":
|
||||
target = dockerhubTarget
|
||||
} else if reqTarget == "ghcr.io" {
|
||||
case "ghcr.io":
|
||||
target = ghcrTarget
|
||||
} else {
|
||||
default:
|
||||
target = reqTarget
|
||||
}
|
||||
} else {
|
||||
@@ -132,11 +132,6 @@ func GhcrRequest(ctx context.Context, c *touka.Context, u string, image *imageIn
|
||||
return
|
||||
}
|
||||
|
||||
//c.Request.Header.VisitAll(func(key, value []byte) {
|
||||
// headerKey := string(key)
|
||||
// headerValue := string(value)
|
||||
// req.Header.Add(headerKey, headerValue)
|
||||
//})
|
||||
copyHeader(c.Request.Header, req.Header)
|
||||
|
||||
req.Header.Set("Host", target)
|
||||
@@ -154,8 +149,9 @@ func GhcrRequest(ctx context.Context, c *touka.Context, u string, image *imageIn
|
||||
return
|
||||
}
|
||||
|
||||
// 处理状态码
|
||||
if resp.StatusCode == 401 {
|
||||
switch resp.StatusCode {
|
||||
|
||||
case 401:
|
||||
// 请求target /v2/路径
|
||||
if string(c.GetRequestURIPath()) != "/v2/" {
|
||||
resp.Body.Close()
|
||||
@@ -181,13 +177,7 @@ func GhcrRequest(ctx context.Context, c *touka.Context, u string, image *imageIn
|
||||
HandleError(c, fmt.Sprintf("Failed to create request: %v", err))
|
||||
return
|
||||
}
|
||||
/*
|
||||
c.Request.Header.VisitAll(func(key, value []byte) {
|
||||
headerKey := string(key)
|
||||
headerValue := string(value)
|
||||
req.Header.Add(headerKey, headerValue)
|
||||
})
|
||||
*/
|
||||
|
||||
copyHeader(c.Request.Header, req.Header)
|
||||
|
||||
req.Header.Set("Host", target)
|
||||
@@ -202,9 +192,20 @@ func GhcrRequest(ctx context.Context, c *touka.Context, u string, image *imageIn
|
||||
}
|
||||
}
|
||||
|
||||
} else if resp.StatusCode == 404 { // 错误处理(404)
|
||||
case 404: // 错误处理(404)
|
||||
ErrorPage(c, NewErrorWithStatusLookup(404, "Page Not Found (From Github)"))
|
||||
return
|
||||
case 302, 301:
|
||||
finalURL := resp.Header.Get("Location")
|
||||
if finalURL != "" {
|
||||
err = resp.Body.Close()
|
||||
if err != nil {
|
||||
c.Errorf("Failed to close response body: %v", err)
|
||||
}
|
||||
c.Infof("Internal Redirecting to %s", finalURL)
|
||||
GhcrRequest(ctx, c, finalURL, image, cfg, target)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -234,14 +235,6 @@ func GhcrRequest(ctx context.Context, c *touka.Context, u string, image *imageIn
|
||||
}
|
||||
}
|
||||
|
||||
// 复制响应头,排除需要移除的 header
|
||||
/*
|
||||
for key, values := range resp.Header {
|
||||
for _, value := range values {
|
||||
c.Response.Header.Add(key, value)
|
||||
}
|
||||
}
|
||||
*/
|
||||
c.SetHeaders(resp.Header)
|
||||
|
||||
c.Status(resp.StatusCode)
|
||||
|
||||
@@ -20,6 +20,19 @@ func HandleError(c *touka.Context, message string) {
|
||||
c.Errorf("%s %s %s %s %s Error: %v", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.UserAgent(), c.Request.Proto, message)
|
||||
}
|
||||
|
||||
func UnifiedToukaErrorHandler(c *touka.Context, code int, err error) {
|
||||
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
c.Errorf("%s %s %s %s %s Error: %v", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.UserAgent(), c.Request.Proto, errMsg)
|
||||
|
||||
constructedGHErr := NewErrorWithStatusLookup(code, errMsg)
|
||||
|
||||
ErrorPage(c, constructedGHErr)
|
||||
}
|
||||
|
||||
type GHProxyErrors struct {
|
||||
StatusCode int
|
||||
StatusDesc string
|
||||
@@ -65,6 +78,25 @@ var (
|
||||
StatusText: "服务器内部错误",
|
||||
HelpInfo: "服务器处理您的请求时发生错误,请稍后重试或联系管理员。",
|
||||
}
|
||||
// 502
|
||||
ErrBadGateway = &GHProxyErrors{
|
||||
StatusCode: 502,
|
||||
StatusDesc: "Bad Gateway",
|
||||
StatusText: "网关错误",
|
||||
HelpInfo: "代理服务器从上游服务器接收到无效响应。",
|
||||
}
|
||||
ErrServiceUnavailable = &GHProxyErrors{
|
||||
StatusCode: 503,
|
||||
StatusDesc: "Service Unavailable",
|
||||
StatusText: "服务不可用",
|
||||
HelpInfo: "服务器目前无法处理请求,通常是由于服务器过载或停机维护。",
|
||||
}
|
||||
ErrGatewayTimeout = &GHProxyErrors{
|
||||
StatusCode: 504,
|
||||
StatusDesc: "Gateway Timeout",
|
||||
StatusText: "网关超时",
|
||||
HelpInfo: "代理服务器未能及时从上游服务器接收到响应。",
|
||||
}
|
||||
)
|
||||
|
||||
var statusErrorMap map[int]*GHProxyErrors
|
||||
@@ -169,11 +201,11 @@ func NewSizedLRUCache(maxBytes int64) (*SizedLRUCache, error) {
|
||||
// 当内部 LRU 缓存因其自身的条目容量限制或 RemoveOldest 方法被调用而逐出条目时,
|
||||
// 此回调函数会被执行,从而更新 currentBytes。
|
||||
var err error
|
||||
c.cache, err = lru.NewWithEvict[string, []byte](10000, func(key string, value []byte) {
|
||||
//c.cache, err = lru.NewWithEvict[string, []byte](10000, func(key string, value []byte) {
|
||||
c.cache, err = lru.NewWithEvict(10000, func(key string, value []byte) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.currentBytes -= int64(len(value))
|
||||
//logDebug("LRU evicted key: %s, size: %d, current total: %d", key, len(value), c.currentBytes)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -195,7 +227,6 @@ func (c *SizedLRUCache) Add(key string, value []byte) {
|
||||
|
||||
// 如果待添加的条目本身就大于缓存的最大容量,则不进行缓存。
|
||||
if itemSize > c.maxBytes {
|
||||
//c.Warnf("Item key %s (size %d) larger than cache max capacity %d. Not caching.", key, itemSize, c.maxBytes)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -203,23 +234,19 @@ func (c *SizedLRUCache) Add(key string, value []byte) {
|
||||
if oldVal, ok := c.cache.Get(key); ok {
|
||||
c.currentBytes -= int64(len(oldVal))
|
||||
c.cache.Remove(key)
|
||||
//logDebug("Key %s exists, removed old size %d. Current total: %d", key, len(oldVal), c.currentBytes)
|
||||
}
|
||||
|
||||
// 主动逐出最旧的条目,直到有足够的空间容纳新条目。
|
||||
for c.currentBytes+itemSize > c.maxBytes && c.cache.Len() > 0 {
|
||||
_, _, existed := c.cache.RemoveOldest()
|
||||
if !existed {
|
||||
//c.Warnf("Attempted to remove oldest, but item not found.")
|
||||
break
|
||||
}
|
||||
//logDebug("Proactively evicted item (size %d) to free space. Current total: %d", len(oldVal), c.currentBytes)
|
||||
}
|
||||
|
||||
// 添加新条目到内部 LRU 缓存。
|
||||
c.cache.Add(key, value)
|
||||
c.currentBytes += itemSize // 手动增加新条目的大小到 currentBytes。
|
||||
//logDebug("Item added: key %s, size: %d, current total: %d", key, itemSize, c.currentBytes)
|
||||
}
|
||||
|
||||
const maxErrorPageCacheBytes = 512 * 1024 // 错误页面缓存的最大容量:512KB
|
||||
@@ -231,7 +258,6 @@ func init() {
|
||||
var err error
|
||||
errorPageCache, err = NewSizedLRUCache(maxErrorPageCacheBytes)
|
||||
if err != nil {
|
||||
// logError("Failed to initialize error page LRU cache: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -283,6 +309,16 @@ func htmlTemplateRender(data interface{}) ([]byte, error) {
|
||||
}
|
||||
|
||||
func ErrorPage(c *touka.Context, errInfo *GHProxyErrors) {
|
||||
|
||||
select {
|
||||
case <-c.Request.Context().Done():
|
||||
return
|
||||
default:
|
||||
if c.Writer.Written() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 将 errInfo 转换为 ErrorPageData 结构体
|
||||
var err error
|
||||
var cacheKey string
|
||||
|
||||
@@ -30,7 +30,11 @@ func GitReq(ctx context.Context, c *touka.Context, u string, cfg *config.Config,
|
||||
return
|
||||
}
|
||||
// 构建新url
|
||||
u = cfg.GitClone.SmartGitAddr + userPath + repoPath + remainingPath + "?" + queryParams.Encode()
|
||||
var paramStr string
|
||||
if len(queryParams) > 0 {
|
||||
paramStr = "?" + queryParams.Encode()
|
||||
}
|
||||
u = cfg.GitClone.SmartGitAddr + userPath + repoPath + remainingPath + paramStr
|
||||
}
|
||||
|
||||
if cfg.GitClone.Mode == "cache" {
|
||||
|
||||
100
proxy/match.go
100
proxy/match.go
@@ -28,7 +28,6 @@ func init() {
|
||||
gistPrefixLen = len(gistPrefix)
|
||||
gistContentPrefixLen = len(gistContentPrefix)
|
||||
apiPrefixLen = len(apiPrefix)
|
||||
//log.Printf("githubPrefixLen: %d, rawPrefixLen: %d, gistPrefixLen: %d, apiPrefixLen: %d", githubPrefixLen, rawPrefixLen, gistPrefixLen, apiPrefixLen)
|
||||
}
|
||||
|
||||
// Matcher 从原始URL路径中高效地解析并匹配代理规则.
|
||||
@@ -159,105 +158,6 @@ func Matcher(rawPath string, cfg *config.Config) (string, string, string, *GHPro
|
||||
return "", "", "", NewErrorWithStatusLookup(404, "no matcher found for the given path")
|
||||
}
|
||||
|
||||
// 原实现
|
||||
/*
|
||||
func Matcher(rawPath string, cfg *config.Config) (string, string, string, *GHProxyErrors) {
|
||||
var (
|
||||
user string
|
||||
repo string
|
||||
matcher string
|
||||
)
|
||||
// 匹配 "https://github.com"开头的链接
|
||||
if strings.HasPrefix(rawPath, "https://github.com") {
|
||||
remainingPath := strings.TrimPrefix(rawPath, "https://github.com")
|
||||
|
||||
//if strings.HasPrefix(remainingPath, "/") {
|
||||
// remainingPath = strings.TrimPrefix(remainingPath, "/")
|
||||
//}
|
||||
|
||||
remainingPath = strings.TrimPrefix(remainingPath, "/")
|
||||
// 预期格式/user/repo/more...
|
||||
// 取出user和repo和最后部分
|
||||
parts := strings.Split(remainingPath, "/")
|
||||
if len(parts) <= 2 {
|
||||
errMsg := "Not enough parts in path after matching 'https://github.com*'"
|
||||
return "", "", "", NewErrorWithStatusLookup(400, errMsg)
|
||||
}
|
||||
user = parts[0]
|
||||
repo = parts[1]
|
||||
// 匹配 "https://github.com"开头的链接
|
||||
if len(parts) >= 3 {
|
||||
switch parts[2] {
|
||||
case "releases", "archive":
|
||||
matcher = "releases"
|
||||
case "blob":
|
||||
matcher = "blob"
|
||||
case "raw":
|
||||
matcher = "raw"
|
||||
case "info", "git-upload-pack":
|
||||
matcher = "clone"
|
||||
default:
|
||||
errMsg := "Url Matched 'https://github.com*', but didn't match the next matcher"
|
||||
return "", "", "", NewErrorWithStatusLookup(400, errMsg)
|
||||
}
|
||||
}
|
||||
return user, repo, matcher, nil
|
||||
}
|
||||
// 匹配 "https://raw"开头的链接
|
||||
if strings.HasPrefix(rawPath, "https://raw") {
|
||||
remainingPath := strings.TrimPrefix(rawPath, "https://")
|
||||
parts := strings.Split(remainingPath, "/")
|
||||
if len(parts) <= 3 {
|
||||
errMsg := "URL after matched 'https://raw*' should have at least 4 parts (user/repo/branch/file)."
|
||||
return "", "", "", NewErrorWithStatusLookup(400, errMsg)
|
||||
}
|
||||
user = parts[1]
|
||||
repo = parts[2]
|
||||
matcher = "raw"
|
||||
|
||||
return user, repo, matcher, nil
|
||||
}
|
||||
// 匹配 "https://gist"开头的链接
|
||||
if strings.HasPrefix(rawPath, "https://gist") {
|
||||
remainingPath := strings.TrimPrefix(rawPath, "https://")
|
||||
parts := strings.Split(remainingPath, "/")
|
||||
if len(parts) <= 3 {
|
||||
errMsg := "URL after matched 'https://gist*' should have at least 4 parts (user/gist_id)."
|
||||
return "", "", "", NewErrorWithStatusLookup(400, errMsg)
|
||||
}
|
||||
user = parts[1]
|
||||
repo = ""
|
||||
matcher = "gist"
|
||||
return user, repo, matcher, nil
|
||||
}
|
||||
// 匹配 "https://api.github.com/"开头的链接
|
||||
if strings.HasPrefix(rawPath, "https://api.github.com/") {
|
||||
matcher = "api"
|
||||
remainingPath := strings.TrimPrefix(rawPath, "https://api.github.com/")
|
||||
|
||||
parts := strings.Split(remainingPath, "/")
|
||||
if parts[0] == "repos" {
|
||||
user = parts[1]
|
||||
repo = parts[2]
|
||||
}
|
||||
if parts[0] == "users" {
|
||||
user = parts[1]
|
||||
}
|
||||
if !cfg.Auth.ForceAllowApi {
|
||||
if cfg.Auth.Method != "header" || !cfg.Auth.Enabled {
|
||||
//return "", "", "", ErrAuthHeaderUnavailable
|
||||
errMsg := "AuthHeader Unavailable, Need to open header auth to enable api proxy"
|
||||
return "", "", "", NewErrorWithStatusLookup(403, errMsg)
|
||||
}
|
||||
}
|
||||
return user, repo, matcher, nil
|
||||
}
|
||||
//return "", "", "", ErrNotFound
|
||||
errMsg := "Didn't match any matcher"
|
||||
return "", "", "", NewErrorWithStatusLookup(404, errMsg)
|
||||
}
|
||||
*/
|
||||
|
||||
var (
|
||||
proxyableMatchersMap map[string]struct{}
|
||||
initMatchersOnce sync.Once
|
||||
|
||||
Reference in New Issue
Block a user