Compare commits

...

26 Commits

Author SHA1 Message Date
WJQSERVER
822b6c8cea 1.3.1 2024-10-06 19:19:54 +08:00
WJQSERVER
5ac08bba56 1.3.0 2024-10-06 04:32:55 +08:00
WJQSERVER
61e741c9b3 24w09b 2024-10-06 04:01:53 +08:00
WJQSERVER
815b86c6c6 24w09a 2024-10-06 03:36:59 +08:00
WJQSERVER
999016be2b fix 2024-10-06 01:54:47 +08:00
WJQSERVER
af6c6cfe64 fix 2024-10-06 01:49:57 +08:00
WJQSERVER
88ee8abb5c fix 2024-10-06 01:43:24 +08:00
WJQSERVER
2d9ce57e90 fix 2024-10-06 01:40:22 +08:00
WJQSERVER
d33377087f fix 2024-10-06 01:36:52 +08:00
WJQSERVER
c78d114767 fix 2024-10-06 01:20:34 +08:00
WJQSERVER
b87a8de3c4 fix 2024-10-06 01:03:38 +08:00
WJQSERVER
5dbf137116 fix 2024-10-06 00:26:53 +08:00
WJQSERVER
57f67278a3 test 2024-10-06 00:22:42 +08:00
WJQSERVER
b9a7f30705 fix 2024-10-05 23:53:09 +08:00
WJQSERVER
c0a9ed11e3 fix 2024-10-05 23:41:19 +08:00
WJQSERVER
eec50879e9 fix 2024-10-05 23:36:22 +08:00
WJQSERVER
862b92a1c5 fix 2024-10-05 23:27:13 +08:00
WJQSERVER
1d7780a890 fix 2024-10-05 23:21:10 +08:00
WJQSERVER
ee215eff36 fix 2024-10-05 23:15:46 +08:00
WJQSERVER
20b9c7827d dev-fix 2024-10-05 22:53:40 +08:00
WJQSERVER
89e6be7709 24w08b 2024-10-05 22:42:43 +08:00
WJQSERVER
822c08d4c0 1.2.0 2024-10-05 04:11:20 +08:00
里見 灯花
8588d66a6c Update Caddyfile 2024-10-05 03:02:19 +08:00
WJQSERVER
e4713d0f50 24w08a 2024-10-03 10:39:53 +08:00
WJQSERVER
51d84f0fc3 update 2024-10-02 22:27:23 +08:00
WJQSERVER
912b6c0279 update 2024-10-02 22:20:02 +08:00
18 changed files with 415 additions and 86 deletions

19
.github/workflows/auto-assign.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Auto Assign
on:
issues:
types: [opened]
pull_request:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: 'Auto-assign issue'
uses: pozil/auto-assign-issue@v1
with:
repo-token: ${{ secrets.AUTO_ASSIGN }}
assignees: WJQSERVER, satomitoka
numOfAssignee: 2

View File

@@ -1,5 +1,62 @@
# 更新日志
v1.3.1
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 剃刀计划,减少多余日志输出
- CHANGE: 调整缓存参数
24w10a
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 剃刀计划,减少多余日志输出
- CHANGE: 调整缓存参数
v1.3.0
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 优化黑名单功能,提升稳定性
- CHANGE: 剃刀计划,减少多余日志输出
- ADD 新增auth子模块blacklist.go,支持黑名单功能
- ADD: 新增blacklist.json文件,用于配置黑名单
- CHANGE: config.yaml文件格式修改,使其具备更好的可读性
- WARNING: 此版本为大版本更新,配置文件重构,此版本不再向前兼容,请注意备份文件并重新部署
24w09b
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 修正配置,提升稳定性
- WARNING: 此版本配置文件重构,此版本不再向前兼容,请注意备份文件并重新部署
24w09a
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 优化黑名单功能,提升稳定性
- CHANGE&ADD: 新增auth子模块blacklist.go
- CHANGE: 黑名单转为使用json文件存储,便于程序处理
- WARNING: 此版本配置文件重构,此版本不再向前兼容,请注意备份文件并重新部署
24w08b
---
- CHANGE: 优化代码结构,提升性能
- ADD & CHANGE: 新增仓库黑名单功能,改进Auth模块
- ADD: 新增blacklist.yaml文件,用于配置仓库黑名单
- CHANGE: 大幅度修改Config包,使其更加模块化
- CHANGE: 与Config包同步修改config.yaml文件(不向前兼容)
- CHANGE: 修改config.yaml文件的格式,使其具备更好的可读性
- WARNING: 此版本配置文件重构,此版本不再向前兼容,请注意备份文件并重新部署
v1.2.0
---
- CHANGE: 优化代码结构,提升性能
- CHANGE: 同步更新logger模块与golang-temp项目定义的开发规范保持一致
- ADD: 新增日志翻转功能
24w08a
---
- CHANGE: 同步更新logger模块与golang-temp项目定义的开发规范保持一致
- ADD: 新增日志翻转功能
v1.1.1
---
- CHANGE: 修改部分代码与golang-temp项目定义的开发规范保持一致

View File

@@ -1 +1 @@
24w07b
24w10a

View File

@@ -16,6 +16,7 @@
- 支持Docker部署
- 支持速率限制
- 支持用户鉴权
- 支持自定义黑名单
- 符合[RFC 7234](https://httpwg.org/specs/rfc7234.html)的HTTP Cache
- 使用Caddy作为Web Server
- 基于[WJQSERVER-STUDIO/golang-temp](https://github.com/WJQSERVER-STUDIO/golang-temp)模板构建,具有标准化的日志记录与构建流程
@@ -62,19 +63,51 @@ docker run -p 7210:80 -v ./ghproxy/log/run:/data/ghproxy/log -v ./ghproxy/log/ca
本项目采用config.yaml作为外部配置,默认配置如下
使用Docker部署时,慎重修改config.yaml,以免造成不必要的麻烦
```yaml
# 核心配置
server:
port: 8080 # 监听端口(小白请勿修改)
host: "127.0.0.1" # 监听地址(小白请勿修改)
sizelimit: 131072000 # 125MB
# 日志配置
logger:
logfilepath: "/data/ghproxy/log/ghproxy.log" # 日志文件路径(小白请勿修改)
maxlogsize: 5 # MB
# CORS 配置
cors:
enabled: true # 是否开启CORS
# 鉴权配置
auth:
enabled: false # 是否开启鉴权
authtoken: "test" # 鉴权Token
# 黑名单配置
blacklist:
enabled: true
blacklistfile: "/data/ghproxy/config/blacklist.json"
```
port: 8080 # 监听端口
host: "127.0.0.1" # 监听地址
sizelimit: 131072000 # 125MB
logfilepath: "/data/ghproxy/log/ghproxy.log" # 日志文件路径
CorsAllowOrigins: true # 是否允许跨域请求
auth: true # 是否开启鉴权
authtoken: "test" # 鉴权token
```
### 黑名单配置
黑名单配置位于config/blacklist.json,格式如下:
```json
{
"blacklist": [
"test/test1",
"example/repo2",
"another/repo3"
]
}
```
### Caddy反代配置
```
```Caddyfile
example.com {
reverse_proxy {
to 127.0.0.1:7210
@@ -94,6 +127,7 @@ example.com {
- [x] 允许更多参数通过config结构传入
- [x] 改进程序效率
- [x] 用户鉴权
- [x] 仓库黑名单
### DEV

View File

@@ -1 +1 @@
1.1.1
1.3.1

View File

@@ -11,8 +11,7 @@ var logw = logger.Logw
func AuthHandler(c *gin.Context, cfg *config.Config) bool {
// 如果身份验证未启用,直接返回 true
if !cfg.Auth {
logw("auth PASSED")
if !cfg.Auth.Enabled {
return true
}
@@ -26,10 +25,11 @@ func AuthHandler(c *gin.Context, cfg *config.Config) bool {
return false
}
isValid := authToken == cfg.AuthToken
isValid := authToken == cfg.Auth.AuthToken
if !isValid {
logw("auth FAILED: invalid auth_token: %s", authToken)
}
logw("auth SUCCESS: %t", isValid)
return isValid
}

45
auth/blacklist.go Normal file
View File

@@ -0,0 +1,45 @@
package auth
import (
"encoding/json"
"ghproxy/config"
"os"
)
type Config struct {
Blacklist []string `json:"blacklist"`
}
var (
cfg *config.Config
blacklistfile = "/data/ghproxy/config/blacklist.json"
blacklist *Config
)
func LoadBlacklist(cfg *config.Config) {
blacklistfile = cfg.Blacklist.BlacklistFile
blacklist = &Config{}
data, err := os.ReadFile(blacklistfile)
if err != nil {
logw("Failed to read blacklist file: %v", err)
}
err = json.Unmarshal(data, blacklist)
if err != nil {
logw("Failed to unmarshal blacklist JSON: %v", err)
}
}
func CheckBlacklist(fullrepo string) bool {
return forRangeCheck(blacklist.Blacklist, fullrepo)
}
func forRangeCheck(blist []string, fullrepo string) bool {
for _, blocked := range blist {
if blocked == fullrepo {
return true
}
}
return false
}

View File

@@ -60,12 +60,6 @@
header_up X-Forwarded-Proto {http.request.header.CF-Visitor}
}
(buffer) {
flush_interval 2000s
buffer_responses
max_buffer_size 256k
}
(rate_limit) {
route /* {
rate_limit {remote.ip} {args[0]}r/m 10000 429
@@ -78,12 +72,10 @@
import header_realip
}
import log ghproxy
import cache 0s 600s
import cache 0s 300s
import error_page
import encode
route /* {
rate_limit {remote.ip} 60r/m 10000 429
}
import rate_limit 60
route / {
root /data/www
file_server
@@ -92,7 +84,7 @@
route /favicon.ico {
root /data/www
file_server
import cache 60s 24h
import cache 0s 24h
}
handle_errors {
@redirects `{err.status_code} in [301, 302, 307]`

View File

@@ -60,12 +60,6 @@
header_up X-Forwarded-Proto {http.request.header.CF-Visitor}
}
(buffer) {
flush_interval 2000s
buffer_responses
max_buffer_size 256k
}
(rate_limit) {
route /* {
rate_limit {remote.ip} {args[0]}r/m 10000 429
@@ -78,7 +72,7 @@
import header_realip
}
import log ghproxy
import cache 0s 600s
import cache 0s 300s
import error_page
import encode
route /* {
@@ -92,7 +86,7 @@
route /favicon.ico {
root /data/www
file_server
import cache 60s 24h
import cache 0s 24h
}
}

8
config/blacklist.json Normal file
View File

@@ -0,0 +1,8 @@
{
"blacklist": [
"test/test1",
"example/repo2",
"another/repo3"
]
}

View File

@@ -7,25 +7,46 @@ import (
)
type Config struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
SizeLimit int `yaml:"sizelimit"`
LogFilePath string `yaml:"logfilepath"`
CORSOrigin bool `yaml:"CorsAllowOrigins"`
Auth bool `yaml:"auth"`
AuthToken string `yaml:"authtoken"`
Server struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
SizeLimit int `yaml:"sizelimit"`
} `yaml:"server"`
Log struct {
LogFilePath string `yaml:"logfilepath"`
MaxLogSize int `yaml:"maxlogsize"`
} `yaml:"logger"`
CORS struct {
Enabled bool `yaml:"enabled"`
} `yaml:"cors"`
Auth struct {
Enabled bool `yaml:"enabled"`
AuthToken string `yaml:"authtoken"`
} `yaml:"auth"`
Blacklist struct {
Enabled bool `yaml:"enabled"`
BlacklistFile string `yaml:"blacklistfile"`
} `yaml:"blacklist"`
}
// LoadConfig 从 YAML 配置文件加载配置
func LoadConfig(filePath string) (*Config, error) {
var config Config
data, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(data, &config)
if err != nil {
if err := loadYAML(filePath, &config); err != nil {
return nil, err
}
return &config, nil
}
// LoadyamlConfig 从 YAML 配置文件加载配置
func loadYAML(filePath string, out interface{}) error {
data, err := os.ReadFile(filePath)
if err != nil {
return err
}
return yaml.Unmarshal(data, out)
}

View File

@@ -1,7 +1,24 @@
port: 8080
host: "127.0.0.1"
sizelimit: 131072000 # 125MB
logfilepath: "/data/ghproxy/log/ghproxy.log"
CorsAllowOrigins: true
auth: false
authtoken: "test"
# Server Configuration
server:
port: 8080
host: "127.0.0.1"
sizelimit: 131072000 # 125MB
# Logging Configuration
logger:
logfilepath: "/data/ghproxy/log/ghproxy.log"
maxlogsize: 5 # MB
# CORS Configuration
cors:
enabled: true
# Authentication Configuration
auth:
enabled: false
authtoken: "test"
# Blacklist Configuration
blacklist:
enabled: true
blacklistfile: "/data/ghproxy/config/blacklist.json"

View File

@@ -13,6 +13,7 @@ RUN wget -O /data/caddy/Caddyfile https://raw.githubusercontent.com/${USER}/${RE
RUN VERSION=$(curl -s https://raw.githubusercontent.com/${USER}/${REPO}/main/DEV-VERSION) && \
wget -O /data/${APPLICATION}/${APPLICATION} https://github.com/${USER}/${REPO}/releases/download/$VERSION/${APPLICATION}
RUN wget -O /data/${APPLICATION}/config.yaml https://raw.githubusercontent.com/${USER}/${REPO}/main/config/config.yaml
RUN wget -O /data/${APPLICATION}/blacklist.json https://raw.githubusercontent.com/${USER}/${REPO}/main/config/blacklist.json
RUN wget -O /usr/local/bin/init.sh https://raw.githubusercontent.com/${USER}/${REPO}/main/init.sh
RUN chmod +x /data/${APPLICATION}/${APPLICATION}
RUN chmod +x /usr/local/bin/init.sh

View File

@@ -13,6 +13,7 @@ RUN wget -O /data/caddy/Caddyfile https://raw.githubusercontent.com/${USER}/${RE
RUN VERSION=$(curl -s https://raw.githubusercontent.com/${USER}/${REPO}/main/VERSION) && \
wget -O /data/${APPLICATION}/${APPLICATION} https://github.com/${USER}/${REPO}/releases/download/$VERSION/${APPLICATION}
RUN wget -O /data/${APPLICATION}/config.yaml https://raw.githubusercontent.com/${USER}/${REPO}/main/config/config.yaml
RUN wget -O /data/${APPLICATION}/blacklist.json https://raw.githubusercontent.com/${USER}/${REPO}/main/config/blacklist.json
RUN wget -O /usr/local/bin/init.sh https://raw.githubusercontent.com/${USER}/${REPO}/main/init.sh
RUN chmod +x /data/${APPLICATION}/${APPLICATION}
RUN chmod +x /usr/local/bin/init.sh

View File

@@ -6,6 +6,10 @@ if [ ! -f /data/caddy/config/Caddyfile ]; then
cp /data/caddy/Caddyfile /data/caddy/config/Caddyfile
fi
if [ ! -f /data/${APPLICATON}/config/blacklist.json ]; then
cp /data/${APPLICATON}/blacklist.json /data/${APPLICATON}/config/blacklist.json
fi
if [ ! -f /data/${APPLICATON}/config/config.yaml ]; then
cp /data/${APPLICATON}/config.yaml /data/${APPLICATON}/config/config.yaml
fi

View File

@@ -1,30 +1,40 @@
// logger/logger.go
package logger
import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sync"
"time"
)
var (
logFile *os.File
logger *log.Logger
logChannel = make(chan string, 100) // 创建一个缓冲通道
quitChannel = make(chan struct{}) // 用于通知退出
logw = Logw
logFile *os.File
logger *log.Logger
logChannel = make(chan string, 100)
quitChannel = make(chan struct{})
logFileMutex sync.Mutex // 保护 logFile 的互斥锁
)
// Init 初始化日志记录器,接受日志文件路径作为参数
func Init(logFilePath string) error {
func Init(logFilePath string, maxLogsize int) error {
logFileMutex.Lock()
defer logFileMutex.Unlock()
var err error
logFile, err = os.OpenFile(logFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
logger = log.New(logFile, "", 0) // 不使用默认前缀
logger = log.New(logFile, "", 0)
go logWorker() // 启动 goroutine 处理日志
go logWorker()
go monitorLogSize(logFilePath, maxLogsize)
return nil
}
@@ -34,30 +44,116 @@ func logWorker() {
select {
case msg := <-logChannel:
timestamp := time.Now().Format("02/Jan/2006:15:04:05 -0700")
logger.Println(timestamp + " - " + msg) // 写入日志
logger.Println(timestamp + " - " + msg)
case <-quitChannel:
return // 退出 goroutine
return
}
}
}
// Log 直接记录日志的函数
func Log(customMessage string) {
logChannel <- customMessage // 将日志消息发送到通道
logChannel <- customMessage
}
// Logw 用于格式化日志记录
func Logw(format string, args ...interface{}) {
message := fmt.Sprintf(format, args...) // 格式化消息
Log(message) // 记录日志
message := fmt.Sprintf(format, args...)
Log(message)
}
// Close 关闭日志文件
func Close() {
logFileMutex.Lock()
defer logFileMutex.Unlock()
if logFile != nil {
quitChannel <- struct{}{} // 通知日志 goroutine 退出
quitChannel <- struct{}{}
if err := logFile.Close(); err != nil {
Log("Error closing log file: " + err.Error()) // 记录关闭日志时的错误
fmt.Printf("Error closing log file: %v", err)
}
}
}
func monitorLogSize(logFilePath string, maxLogsize int) {
var maxLogsizeBytes int64 = int64(maxLogsize) * 1024 * 1024 // 最大日志文件大小单位为MB
for {
time.Sleep(600 * time.Second) // 每10分钟检查一次
logFileMutex.Lock()
info, err := logFile.Stat()
logFileMutex.Unlock()
if err == nil && info.Size() > maxLogsizeBytes {
if err := rotateLogFile(logFilePath); err != nil {
logw("Log Rotation Failed: %s", err)
}
}
}
}
func rotateLogFile(logFilePath string) error {
logFileMutex.Lock()
defer logFileMutex.Unlock()
if logFile != nil {
if err := logFile.Close(); err != nil {
logw("Error closing log file for rotation: %v", err)
}
}
// 打开当前日志文件
logFile, err := os.Open(logFilePath)
if err != nil {
return fmt.Errorf("failed to open log file: %s, error: %w", logFilePath, err)
}
defer logFile.Close()
newLogFilePath := logFilePath + "-" + time.Now().Format("20060102-150405") + ".tar.gz"
outFile, err := os.Create(newLogFilePath)
if err != nil {
return fmt.Errorf("failed to create gz file: %s, error: %w", newLogFilePath, err)
}
defer outFile.Close()
gzWriter, err := gzip.NewWriterLevel(outFile, gzip.BestCompression)
if err != nil {
return fmt.Errorf("failed to create gz writer: %w", err)
}
defer gzWriter.Close()
tarWriter := tar.NewWriter(gzWriter)
defer tarWriter.Close()
logFileStat, err := logFile.Stat()
if err != nil {
return fmt.Errorf("failed to stat log file: %s, error: %w", logFilePath, err)
}
logFileHeader := &tar.Header{
Name: filepath.Base(logFilePath),
Size: logFileStat.Size(),
Mode: 0644,
ModTime: logFileStat.ModTime(),
}
if err := tarWriter.WriteHeader(logFileHeader); err != nil {
return fmt.Errorf("failed to write log file header: %s, error: %w", logFilePath, err)
}
if _, err := io.Copy(tarWriter, logFile); err != nil {
return fmt.Errorf("failed to copy log file: %s, error: %w", logFilePath, err)
}
if err := os.Truncate(logFilePath, 0); err != nil {
return fmt.Errorf("failed to truncate log file: %s, error: %w", logFilePath, err)
}
// 重新打开日志文件
logFile, err = os.OpenFile(logFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return fmt.Errorf("failed to reopen log file: %s, error: %w", logFilePath, err)
}
logger.SetOutput(logFile)
return nil
}

22
main.go
View File

@@ -7,6 +7,7 @@ import (
"net/http"
"regexp"
"ghproxy/auth"
"ghproxy/config"
"ghproxy/logger"
"ghproxy/proxy"
@@ -14,10 +15,12 @@ import (
"github.com/gin-gonic/gin"
)
var cfg *config.Config
var logw = logger.Logw
var router *gin.Engine
var configfile = "/data/ghproxy/config/config.yaml"
var (
cfg *config.Config
logw = logger.Logw
router *gin.Engine
configfile = "/data/ghproxy/config/config.yaml"
)
var (
exps = []*regexp.Regexp{
@@ -42,7 +45,7 @@ func loadConfig() {
func setupLogger() {
// 初始化日志模块
var err error
err = logger.Init(cfg.LogFilePath) // 传递日志文件路径
err = logger.Init(cfg.Log.LogFilePath, cfg.Log.MaxLogSize) // 传递日志文件路径
if err != nil {
log.Fatalf("Failed to initialize logger: %v", err)
}
@@ -50,9 +53,14 @@ func setupLogger() {
logw("Init Completed")
}
func LoadBlacklist(cfg *config.Config) {
auth.LoadBlacklist(cfg)
}
func init() {
loadConfig()
setupLogger()
LoadBlacklist(cfg)
// 设置 Gin 模式
gin.SetMode(gin.ReleaseMode)
@@ -80,7 +88,7 @@ func init() {
func main() {
// 启动服务器
err := router.Run(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port))
err := router.Run(fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port))
if err != nil {
log.Fatalf("Error starting server: %v\n", err)
}
@@ -92,6 +100,6 @@ func api(c *gin.Context) {
// 设置响应头
c.Writer.Header().Set("Content-Type", "application/json")
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
"MaxResponseBodySize": cfg.SizeLimit,
"MaxResponseBodySize": cfg.Server.SizeLimit,
})
}

View File

@@ -18,7 +18,6 @@ import (
)
var logw = logger.Logw
var cfg *config.Config
var exps = []*regexp.Regexp{
regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:releases|archive)/.*`),
@@ -34,11 +33,40 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
re := regexp.MustCompile(`^(http:|https:)?/?/?(.*)`)
matches := re.FindStringSubmatch(rawPath)
if len(matches) < 3 {
logw("Invalid URL: %s", rawPath)
c.String(http.StatusForbidden, "Invalid URL.")
return
}
rawPath = "https://" + matches[2]
// 提取用户名和仓库名,格式为 handle/<username>/<repo>/*
pathmatches := regexp.MustCompile(`^([^/]+)/([^/]+)/([^/]+)/.*`)
pathParts := pathmatches.FindStringSubmatch(matches[2])
if len(pathParts) < 4 {
logw("Invalid path: %s", rawPath)
c.String(http.StatusForbidden, "Invalid path; expected username/repo.")
return
}
username := pathParts[2]
repo := pathParts[3]
logw("Blacklist Check > Username: %s, Repo: %s", username, repo)
fullrepo := fmt.Sprintf("%s/%s", username, repo)
// 黑名单检查
blacklistpass := auth.CheckBlacklist(fullrepo)
if blacklistpass {
errMsg := fmt.Sprintf("Blacklist Blocked repo: %s", fullrepo)
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
logw(errMsg)
return
}
matches = CheckURL(rawPath)
if matches == nil {
c.String(http.StatusForbidden, "Invalid input.")
c.AbortWithStatus(http.StatusNotFound)
return
}
@@ -52,7 +80,6 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
return
}
logw("Request: %s %s", c.Request.Method, rawPath)
logw("Matches: %v", matches)
switch {
@@ -71,7 +98,7 @@ func NoRouteHandler(cfg *config.Config) gin.HandlerFunc {
func ProxyRequest(c *gin.Context, u string, cfg *config.Config, mode string) {
method := c.Request.Method
logw("%s Method: %s", u, method)
logw("%s %s", method, u)
client := req.C()
@@ -129,6 +156,7 @@ func SendRequest(req *req.Request, method, url string) (*req.Response, error) {
case "DELETE":
return req.Delete(url)
default:
logw("Unsupported method: %s", method)
return nil, fmt.Errorf("unsupported method: %s", method)
}
}
@@ -137,7 +165,7 @@ func HandleResponseSize(resp *req.Response, cfg *config.Config, c *gin.Context)
contentLength := resp.Header.Get("Content-Length")
if contentLength != "" {
size, err := strconv.Atoi(contentLength)
if err == nil && size > cfg.SizeLimit {
if err == nil && size > cfg.Server.SizeLimit {
finalURL := resp.Request.URL.String()
c.Redirect(http.StatusMovedPermanently, finalURL)
logw("Redirecting to %s due to size limit (%d bytes)", finalURL, size)
@@ -148,9 +176,13 @@ func HandleResponseSize(resp *req.Response, cfg *config.Config, c *gin.Context)
}
func CopyResponseHeaders(resp *req.Response, c *gin.Context, cfg *config.Config) {
headersToRemove := []string{"Content-Security-Policy", "Referrer-Policy", "Strict-Transport-Security"}
headersToRemove := map[string]struct{}{
"Content-Security-Policy": {},
"Referrer-Policy": {},
"Strict-Transport-Security": {},
}
for _, header := range headersToRemove {
for header := range headersToRemove {
resp.Header.Del(header)
}
@@ -160,10 +192,9 @@ func CopyResponseHeaders(resp *req.Response, c *gin.Context, cfg *config.Config)
}
}
if cfg.CORSOrigin {
c.Header("Access-Control-Allow-Origin", "")
if cfg.CORS.Enabled {
c.Header("Access-Control-Allow-Origin", "*")
} else {
c.Header("Access-Control-Allow-Origin", "")
}
}
@@ -179,6 +210,7 @@ func CheckURL(u string) []string {
return matches[1:]
}
}
logw("Invalid URL: %s", u)
errMsg := fmt.Sprintf("Invalid URL: %s", u)
logw(errMsg)
return nil
}