mirror of
https://github.com/WJQSERVER-STUDIO/ghproxy.git
synced 2026-02-03 00:01:10 +08:00
24w20a
This commit is contained in:
parent
19f753a515
commit
92b3e19954
8 changed files with 70 additions and 50 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
24w20a
|
||||||
|
---
|
||||||
|
- PRE-RELEASE: 此版本是v1.6.2的预发布版本,请勿在生产环境中使用
|
||||||
|
- CHANGE: 大幅修改日志记录,对各个部分的日志记录进行统一格式,并对部分重复日志进行合并
|
||||||
|
- CHANGE: 大幅优化一键部署脚本,使其更加易用,并增加更多的功能(已于早些时候hotfix)
|
||||||
|
- CHANGE: 优化部分代码结构,提升性能
|
||||||
|
|
||||||
v1.6.1
|
v1.6.1
|
||||||
---
|
---
|
||||||
- CHANGE: 根据社区建议,将`sizeLimit`由过去的以`byte`为单位,改为以`MB`为单位,以便于直观理解
|
- CHANGE: 根据社区建议,将`sizeLimit`由过去的以`byte`为单位,改为以`MB`为单位,以便于直观理解
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
24w19d
|
24w20a
|
||||||
|
|
@ -57,7 +57,7 @@ git clone https://ghproxy.1888866.xyz/github.com/WJQSERVER-STUDIO/ghproxy.git
|
||||||
docker run -p 7210:80 -v ./ghproxy/log/run:/data/ghproxy/log -v ./ghproxy/log/caddy:/data/caddy/log -v ./ghproxy/config:/data/ghproxy/config --restart always wjqserver/ghproxy
|
docker run -p 7210:80 -v ./ghproxy/log/run:/data/ghproxy/log -v ./ghproxy/log/caddy:/data/caddy/log -v ./ghproxy/config:/data/ghproxy/config --restart always wjqserver/ghproxy
|
||||||
```
|
```
|
||||||
|
|
||||||
- Docker-Compose
|
- Docker-Compose (建议使用)
|
||||||
|
|
||||||
参看[docker-compose.yml](https://github.com/WJQSERVER-STUDIO/ghproxy/blob/main/docker/compose/docker-compose.yml)
|
参看[docker-compose.yml](https://github.com/WJQSERVER-STUDIO/ghproxy/blob/main/docker/compose/docker-compose.yml)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
| 版本 | 是否支持 |
|
| 版本 | 是否支持 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| v1.x.x | :white_check_mark: |
|
| v1.x.x | :white_check_mark: |
|
||||||
| **w**a/b/c... | :warning: 此为PRE-RELEASE版本,用于开发与测试,可能存在未知的问题 |
|
| 24w*a/b/c... | :warning: 此为PRE-RELEASE版本,用于开发与测试,可能存在未知的问题 |
|
||||||
| v0.x.x | :x: 这些版本不再受支持 |
|
| v0.x.x | :x: 这些版本不再受支持 |
|
||||||
|
|
||||||
### 用户须知
|
### 用户须知
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ func InitHandleRouter(cfg *config.Config, router *gin.Engine) {
|
||||||
|
|
||||||
func SizeLimitHandler(cfg *config.Config, c *gin.Context) {
|
func SizeLimitHandler(cfg *config.Config, c *gin.Context) {
|
||||||
sizeLimit := cfg.Server.SizeLimit
|
sizeLimit := cfg.Server.SizeLimit
|
||||||
|
logInfo("%s %s %s %s %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto)
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||||
"MaxResponseBodySize": sizeLimit,
|
"MaxResponseBodySize": sizeLimit,
|
||||||
|
|
@ -53,6 +54,7 @@ func SizeLimitHandler(cfg *config.Config, c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func WhiteListStatusHandler(c *gin.Context, cfg *config.Config) {
|
func WhiteListStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
|
logInfo("%s %s %s %s %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto)
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||||
"Whitelist": cfg.Whitelist.Enabled,
|
"Whitelist": cfg.Whitelist.Enabled,
|
||||||
|
|
@ -60,6 +62,7 @@ func WhiteListStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BlackListStatusHandler(c *gin.Context, cfg *config.Config) {
|
func BlackListStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
|
logInfo("%s %s %s %s %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto)
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||||
"Blacklist": cfg.Blacklist.Enabled,
|
"Blacklist": cfg.Blacklist.Enabled,
|
||||||
|
|
@ -67,6 +70,7 @@ func BlackListStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CorsStatusHandler(c *gin.Context, cfg *config.Config) {
|
func CorsStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
|
logInfo("%s %s %s %s %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto)
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||||
"Cors": cfg.CORS.Enabled,
|
"Cors": cfg.CORS.Enabled,
|
||||||
|
|
@ -74,6 +78,7 @@ func CorsStatusHandler(c *gin.Context, cfg *config.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func HealthcheckHandler(c *gin.Context) {
|
func HealthcheckHandler(c *gin.Context) {
|
||||||
|
logInfo("%s %s %s %s %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto)
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||||
"Status": "OK",
|
"Status": "OK",
|
||||||
|
|
|
||||||
19
auth/auth.go
19
auth/auth.go
|
|
@ -1,6 +1,7 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"ghproxy/config"
|
"ghproxy/config"
|
||||||
"ghproxy/logger"
|
"ghproxy/logger"
|
||||||
|
|
||||||
|
|
@ -26,27 +27,29 @@ func Init(cfg *config.Config) {
|
||||||
logInfo("Auth Init")
|
logInfo("Auth Init")
|
||||||
}
|
}
|
||||||
|
|
||||||
func AuthHandler(c *gin.Context, cfg *config.Config) bool {
|
func AuthHandler(c *gin.Context, cfg *config.Config) (isValid bool, err string) {
|
||||||
// 如果身份验证未启用,直接返回 true
|
// 如果身份验证未启用,直接返回 true
|
||||||
if !cfg.Auth.Enabled {
|
if !cfg.Auth.Enabled {
|
||||||
return true
|
return true, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取 auth_token 参数
|
// 获取 auth_token 参数
|
||||||
authToken := c.Query("auth_token")
|
authToken := c.Query("auth_token")
|
||||||
logInfo("auth_token received: %s", authToken)
|
// IP METHOD URL USERAGENT PROTO TOKEN
|
||||||
|
logInfo("%s %s %s %s %s AUTH_TOKEN: %s", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Request.UserAgent(), c.Request.Proto, authToken)
|
||||||
|
|
||||||
// 验证 token
|
// 验证 token
|
||||||
if authToken == "" {
|
if authToken == "" {
|
||||||
logWarning("auth FAILED: no auth_token provided")
|
err := "Auth token == nil"
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid := authToken == cfg.Auth.AuthToken
|
isValid = authToken == cfg.Auth.AuthToken
|
||||||
if !isValid {
|
if !isValid {
|
||||||
logWarning("auth FAILED: invalid auth_token: %s", authToken)
|
err := fmt.Sprintf("Auth token incorrect: %s", authToken)
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("auth SUCCESS: %t", isValid)
|
logInfo("auth SUCCESS: %t", isValid)
|
||||||
return isValid
|
return isValid, ""
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
main.go
14
main.go
|
|
@ -22,7 +22,6 @@ var (
|
||||||
cfgfile string
|
cfgfile string
|
||||||
)
|
)
|
||||||
|
|
||||||
// 日志模块
|
|
||||||
var (
|
var (
|
||||||
logw = logger.Logw
|
logw = logger.Logw
|
||||||
logInfo = logger.LogInfo
|
logInfo = logger.LogInfo
|
||||||
|
|
@ -36,7 +35,6 @@ func readFlag() {
|
||||||
|
|
||||||
func loadConfig() {
|
func loadConfig() {
|
||||||
var err error
|
var err error
|
||||||
// 初始化配置
|
|
||||||
cfg, err = config.LoadConfig(cfgfile)
|
cfg, err = config.LoadConfig(cfgfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to load config: %v", err)
|
log.Fatalf("Failed to load config: %v", err)
|
||||||
|
|
@ -46,9 +44,8 @@ func loadConfig() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLogger(cfg *config.Config) {
|
func setupLogger(cfg *config.Config) {
|
||||||
// 初始化日志模块
|
|
||||||
var err error
|
var err error
|
||||||
err = logger.Init(cfg.Log.LogFilePath, cfg.Log.MaxLogSize) // 传递日志文件路径
|
err = logger.Init(cfg.Log.LogFilePath, cfg.Log.MaxLogSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to initialize logger: %v", err)
|
log.Fatalf("Failed to initialize logger: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -89,8 +86,8 @@ func init() {
|
||||||
router.StaticFile("/favicon.ico", faviconPath)
|
router.StaticFile("/favicon.ico", faviconPath)
|
||||||
} else if !cfg.Pages.Enabled {
|
} else if !cfg.Pages.Enabled {
|
||||||
router.GET("/", func(c *gin.Context) {
|
router.GET("/", func(c *gin.Context) {
|
||||||
c.String(http.StatusForbidden, "403 Forbidden This route is not allowed to access.")
|
c.String(http.StatusForbidden, "403 Forbidden Access")
|
||||||
logWarning("Forbidden: IP:%s UA:%s METHOD:%s HTTPv:%s", c.ClientIP(), c.Request.UserAgent(), c.Request.Method, c.Request.Proto)
|
logWarning("403 > Path:/ IP:%s UA:%s METHOD:%s HTTPv:%s", c.ClientIP(), c.Request.UserAgent(), c.Request.Method, c.Request.Proto)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,11 +97,10 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// 启动服务器
|
|
||||||
err := router.Run(fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port))
|
err := router.Run(fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logError("Error starting server: %v\n", err)
|
logError("Failed to start server: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Program finished")
|
fmt.Println("Program Exit")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
// proxy/proxy.go 实验性
|
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -40,8 +39,9 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
|
||||||
matches := re.FindStringSubmatch(rawPath)
|
matches := re.FindStringSubmatch(rawPath)
|
||||||
|
|
||||||
if len(matches) < 3 {
|
if len(matches) < 3 {
|
||||||
logWarning("Invalid URL: %s", rawPath)
|
errMsg := fmt.Sprintf("%s %s %s %s %s Invalid URL", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
c.String(http.StatusForbidden, "Invalid URL.")
|
logWarning(errMsg)
|
||||||
|
c.String(http.StatusForbidden, "Invalid URL Format. Path: %s", rawPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,34 +49,37 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
|
||||||
|
|
||||||
username, repo := MatchUserRepo(rawPath, cfg, c, matches)
|
username, repo := MatchUserRepo(rawPath, cfg, c, matches)
|
||||||
|
|
||||||
logWarning("Blacklist Check > Username: %s, Repo: %s", username, repo)
|
logInfo("%s %s %s %s %s Matched-Username: %s, Matched-Repo: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, username, repo)
|
||||||
fullrepo := fmt.Sprintf("%s/%s", username, repo)
|
fullrepo := fmt.Sprintf("%s/%s", username, repo)
|
||||||
|
|
||||||
// 白名单检查
|
// 白名单检查
|
||||||
if cfg.Whitelist.Enabled {
|
if cfg.Whitelist.Enabled {
|
||||||
whitelistpass := auth.CheckWhitelist(fullrepo)
|
whitelist := auth.CheckWhitelist(fullrepo)
|
||||||
if !whitelistpass {
|
if !whitelist {
|
||||||
|
logErrMsg := fmt.Sprintf("%s %s %s %s %s Whitelist Blocked repo: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, fullrepo)
|
||||||
errMsg := fmt.Sprintf("Whitelist Blocked repo: %s", fullrepo)
|
errMsg := fmt.Sprintf("Whitelist Blocked repo: %s", fullrepo)
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
||||||
logWarning(errMsg)
|
logWarning(logErrMsg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 黑名单检查
|
// 黑名单检查
|
||||||
if cfg.Blacklist.Enabled {
|
if cfg.Blacklist.Enabled {
|
||||||
blacklistpass := auth.CheckBlacklist(fullrepo)
|
blacklist := auth.CheckBlacklist(fullrepo)
|
||||||
if blacklistpass {
|
if blacklist {
|
||||||
|
logErrMsg := fmt.Sprintf("%s %s %s %s %s Whitelist Blocked repo: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, fullrepo)
|
||||||
errMsg := fmt.Sprintf("Blacklist Blocked repo: %s", fullrepo)
|
errMsg := fmt.Sprintf("Blacklist Blocked repo: %s", fullrepo)
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
||||||
logWarning(errMsg)
|
logWarning(logErrMsg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matches = CheckURL(rawPath)
|
matches = CheckURL(rawPath, c)
|
||||||
if matches == nil {
|
if matches == nil {
|
||||||
c.AbortWithStatus(http.StatusNotFound)
|
c.AbortWithStatus(http.StatusNotFound)
|
||||||
|
logError("%s %s %s %s %s 404-NOMATCH", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,13 +87,16 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
|
||||||
rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
|
rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !auth.AuthHandler(c, cfg) {
|
// 鉴权
|
||||||
|
authcheck, err := auth.AuthHandler(c, cfg)
|
||||||
|
if !authcheck {
|
||||||
c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
|
c.AbortWithStatusJSON(401, gin.H{"error": "Unauthorized"})
|
||||||
logWarning("Unauthorized request: %s", rawPath)
|
logWarning("%s %s %s %s %s Auth-Error: %v", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("Matches: %v", matches)
|
// IP METHOD URL USERAGENT PROTO MATCHES
|
||||||
|
logInfo("%s %s %s %s %s Matches: %v", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, matches)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case exps[0].MatchString(rawPath), exps[1].MatchString(rawPath), exps[3].MatchString(rawPath), exps[4].MatchString(rawPath):
|
case exps[0].MatchString(rawPath), exps[1].MatchString(rawPath), exps[3].MatchString(rawPath), exps[4].MatchString(rawPath):
|
||||||
|
|
@ -99,6 +105,7 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
|
||||||
ProxyRequest(c, rawPath, cfg, "git")
|
ProxyRequest(c, rawPath, cfg, "git")
|
||||||
default:
|
default:
|
||||||
c.String(http.StatusForbidden, "Invalid input.")
|
c.String(http.StatusForbidden, "Invalid input.")
|
||||||
|
fmt.Println("Invalid input.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,24 +117,24 @@ func MatchUserRepo(rawPath string, cfg *config.Config, c *gin.Context, matches [
|
||||||
var gistmatches []string
|
var gistmatches []string
|
||||||
if gistregex.MatchString(rawPath) {
|
if gistregex.MatchString(rawPath) {
|
||||||
gistmatches = gistregex.FindStringSubmatch(rawPath)
|
gistmatches = gistregex.FindStringSubmatch(rawPath)
|
||||||
logInfo("Gist Matched > Username: %s, URL: %s", gistmatches[1], rawPath)
|
logInfo("%s %s %s %s %s Matched-Username: %s", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto, gistmatches[1])
|
||||||
return gistmatches[1], ""
|
return gistmatches[1], ""
|
||||||
}
|
}
|
||||||
// 定义路径匹配的正则表达式
|
// 定义路径
|
||||||
pathRegex := regexp.MustCompile(`^([^/]+)/([^/]+)/([^/]+)/.*`)
|
pathRegex := regexp.MustCompile(`^([^/]+)/([^/]+)/([^/]+)/.*`)
|
||||||
if pathMatches := pathRegex.FindStringSubmatch(matches[2]); len(pathMatches) >= 4 {
|
if pathMatches := pathRegex.FindStringSubmatch(matches[2]); len(pathMatches) >= 4 {
|
||||||
return pathMatches[2], pathMatches[3]
|
return pathMatches[2], pathMatches[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回错误信息
|
// 返回错误信息
|
||||||
logWarning("Invalid path: %s", rawPath)
|
errMsg := fmt.Sprintf("%s %s %s %s %s Invalid URL", c.ClientIP(), c.Request.Method, rawPath, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
c.String(http.StatusForbidden, "Invalid path; expected username/repo.")
|
logWarning(errMsg)
|
||||||
|
c.String(http.StatusForbidden, "Invalid path; expected username/repo, Path: %s", rawPath)
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string) {
|
func ProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string) {
|
||||||
method := c.Request.Method
|
method := c.Request.Method
|
||||||
// 记录日志 IP 地址、请求方法、请求 URL、请求头 User-Agent 、HTTP版本
|
|
||||||
logInfo("%s %s %s %s %s", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
logInfo("%s %s %s %s %s", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
|
|
||||||
client := createHTTPClient(mode)
|
client := createHTTPClient(mode)
|
||||||
|
|
@ -141,7 +148,7 @@ func ProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string) {
|
||||||
req := client.R().SetBody(body)
|
req := client.R().SetBody(body)
|
||||||
setRequestHeaders(c, req)
|
setRequestHeaders(c, req)
|
||||||
|
|
||||||
resp, err := SendRequest(req, method, u)
|
resp, err := SendRequest(c, req, method, u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleError(c, fmt.Sprintf("Failed to send request: %v", err))
|
HandleError(c, fmt.Sprintf("Failed to send request: %v", err))
|
||||||
return
|
return
|
||||||
|
|
@ -149,17 +156,18 @@ func ProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string) {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if err := HandleResponseSize(resp, cfg, c); err != nil {
|
if err := HandleResponseSize(resp, cfg, c); err != nil {
|
||||||
logWarning("Error handling response size: %v", err)
|
logWarning("%s %s %s %s %s Response-Size-Error: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyResponseHeaders(resp, c, cfg)
|
CopyResponseHeaders(resp, c, cfg)
|
||||||
c.Status(resp.StatusCode)
|
c.Status(resp.StatusCode)
|
||||||
if err := copyResponseBody(c, resp.Body); err != nil {
|
if err := copyResponseBody(c, resp.Body); err != nil {
|
||||||
logError("Failed to copy response body: %v", err)
|
logError("%s %s %s %s %s Response-Copy-Error: %v", c.ClientIP(), method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断并选择TLS指纹
|
||||||
func createHTTPClient(mode string) *req.Client {
|
func createHTTPClient(mode string) *req.Client {
|
||||||
client := req.C()
|
client := req.C()
|
||||||
switch mode {
|
switch mode {
|
||||||
|
|
@ -198,7 +206,7 @@ func copyResponseBody(c *gin.Context, respBody io.Reader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendRequest(req *req.Request, method, url string) (*req.Response, error) {
|
func SendRequest(c *gin.Context, req *req.Request, method, url string) (*req.Response, error) {
|
||||||
switch method {
|
switch method {
|
||||||
case "GET":
|
case "GET":
|
||||||
return req.Get(url)
|
return req.Get(url)
|
||||||
|
|
@ -209,8 +217,10 @@ func SendRequest(req *req.Request, method, url string) (*req.Response, error) {
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
return req.Delete(url)
|
return req.Delete(url)
|
||||||
default:
|
default:
|
||||||
logInfo("Unsupported method: %s", method)
|
// IP METHOD URL USERAGENT PROTO UNSUPPORTED-METHOD
|
||||||
return nil, fmt.Errorf("unsupported method: %s", method)
|
errmsg := fmt.Sprintf("%s %s %s %s %s Unsupported method", c.ClientIP(), method, url, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
|
logWarning(errmsg)
|
||||||
|
return nil, fmt.Errorf(errmsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,8 +232,8 @@ func HandleResponseSize(resp *req.Response, cfg *config.Config, c *gin.Context)
|
||||||
if err == nil && size > sizelimit {
|
if err == nil && size > sizelimit {
|
||||||
finalURL := resp.Request.URL.String()
|
finalURL := resp.Request.URL.String()
|
||||||
c.Redirect(http.StatusMovedPermanently, finalURL)
|
c.Redirect(http.StatusMovedPermanently, finalURL)
|
||||||
logWarning("Size limit exceeded: %s, Size: %d", finalURL, size)
|
logWarning("%s %s %s %s %s Final-URL: %s Size-Limit-Exceeded: %d", c.ClientIP(), c.Request.Method, c.Request.URL.String(), c.Request.Header.Get("User-Agent"), c.Request.Proto, finalURL, size)
|
||||||
return fmt.Errorf("size limit exceeded: %d", size)
|
return fmt.Errorf("Path: %s size limit exceeded: %d", finalURL, size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -282,14 +292,13 @@ func HandleError(c *gin.Context, message string) {
|
||||||
logWarning(message)
|
logWarning(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckURL(u string) []string {
|
func CheckURL(u string, c *gin.Context) []string {
|
||||||
for _, exp := range exps {
|
for _, exp := range exps {
|
||||||
if matches := exp.FindStringSubmatch(u); matches != nil {
|
if matches := exp.FindStringSubmatch(u); matches != nil {
|
||||||
logInfo("URL matched: %s, Matches: %v", u, matches[1:])
|
|
||||||
return matches[1:]
|
return matches[1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
errMsg := fmt.Sprintf("Invalid URL: %s", u)
|
errMsg := fmt.Sprintf("%s %s %s %s %s Invalid URL", c.ClientIP(), c.Request.Method, u, c.Request.Header.Get("User-Agent"), c.Request.Proto)
|
||||||
logWarning(errMsg)
|
logWarning(errMsg)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue