Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
267dfafcb9 | ||
|
|
e32adadaff | ||
|
|
942dda86e7 | ||
|
|
bbfc7c0d6d | ||
|
|
5af898b3e6 | ||
|
|
3c162bf9d7 | ||
|
|
1eed79463d |
21
.github/workflows/build-dev.yml
vendored
21
.github/workflows/build-dev.yml
vendored
@@ -21,31 +21,36 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Load VERSION
|
||||
- name: 加载版本号
|
||||
run: |
|
||||
if [ -f DEV-VERSION ]; then
|
||||
echo "VERSION=$(cat DEV-VERSION)" >> $GITHUB_ENV
|
||||
else
|
||||
echo "DEV-VERSION file not found!" && exit 1
|
||||
fi
|
||||
- name: Set up Go
|
||||
- name: 安装 Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
- name: Install UPX
|
||||
- name: 安装UPX
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install upx -y
|
||||
- name: Build
|
||||
- name: 编译
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
run: |
|
||||
CGO_ENABLED=0 go build -o ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}} ./main.go
|
||||
CGO_ENABLED=0 go build -ldflags "-X main.version=${{ env.VERSION }}" -o ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}} ./main.go
|
||||
upx -9 ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}}
|
||||
- name: Package
|
||||
- name: 打包
|
||||
run: |
|
||||
tar -czvf ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}}.tar.gz ./${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}}
|
||||
mkdir ghproxyd
|
||||
cp ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}} ./ghproxyd/
|
||||
mv ./ghproxyd/${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}} ./ghproxyd/${{ env.OUTPUT_BINARY }}
|
||||
cp LICENSE ./ghproxyd/
|
||||
tar -czf ${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}}.tar.gz -C ghproxyd .
|
||||
ls
|
||||
- name: Upload to GitHub Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -57,7 +62,7 @@ jobs:
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ env.VERSION }}
|
||||
artifacts: ./${{ env.OUTPUT_BINARY }}*
|
||||
artifacts: ./${{ env.OUTPUT_BINARY }}-${{matrix.goos}}-${{matrix.goarch}}.tar.gz
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ env.VERSION }}
|
||||
allowUpdates: true
|
||||
|
||||
45
.github/workflows/build.yml
vendored
45
.github/workflows/build.yml
vendored
@@ -62,7 +62,8 @@ jobs:
|
||||
tag: ${{ env.VERSION }}
|
||||
allowUpdates: true
|
||||
env:
|
||||
export PATH: $PATH:/usr/local/go/bin
|
||||
export PATH: $PATH:/usr/local/go/bin
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build # 确保这个作业在 build 作业完成后运行
|
||||
@@ -102,3 +103,45 @@ jobs:
|
||||
tags: |
|
||||
${{ env.IMAGE_NAME }}:${{ env.VERSION }}
|
||||
${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
docker-nocache:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build # 确保这个作业在 build 作业完成后运行
|
||||
env:
|
||||
IMAGE_NAME: wjqserver/ghproxy # 定义镜像名称变量
|
||||
DOCKERFILE: docker/dockerfile/nocache/Dockerfile # 定义 Dockerfile 路径变量
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Load VERSION
|
||||
run: |
|
||||
if [ -f VERSION ]; then
|
||||
echo "VERSION=$(cat VERSION)" >> $GITHUB_ENV
|
||||
else
|
||||
echo "VERSION file not found!" && exit 1
|
||||
fi
|
||||
- name: Wait for Compile
|
||||
run: sleep 300s
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: 构建镜像
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
file: ./${{ env.DOCKERFILE }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.IMAGE_NAME }}:${{ env.VERSION }}-nocache
|
||||
${{ env.IMAGE_NAME }}:nocache
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,10 +1,34 @@
|
||||
# 更新日志
|
||||
|
||||
24w21d
|
||||
---
|
||||
- PRE-RELEASE: 此版本是v1.7.0的预发布版本,请勿在生产环境中使用
|
||||
- ADD: 新增`ratePerMinute` API可供查询
|
||||
- ADD: 前端新增 version 标识
|
||||
- ADD: 前端新增 `重定向` 按钮,用于重定向到代理后的链接
|
||||
- CHANGE: 优化输出代码块,使样式更加美观
|
||||
- CHANGE: 更新相关依赖库
|
||||
- CHANGE: 对黑名单模块进行实验性功能优化,提升性能
|
||||
|
||||
24w21c
|
||||
---
|
||||
- PRE-RELEASE: 此版本是v1.7.0的预发布版本,请勿在生产环境中使用
|
||||
- CHANGE: 对编译打包进行改进,此后不再提供独立可执行文件,请改为拉取`tar.gz`压缩包
|
||||
- CHANGE: 由于上述原因,对Docker打包进行相应改进
|
||||
|
||||
24w21b
|
||||
---
|
||||
- PRE-RELEASE: 此版本是v1.7.0的预发布版本,请勿在生产环境中使用
|
||||
- ADD: 加入版本号标识与对应API接口
|
||||
- ADD: 加入速率限制API接口
|
||||
- CHANGE: 修改打包部分
|
||||
|
||||
24w21a
|
||||
---
|
||||
- PRE-RELEASE: 此版本是v1.7.0的预发布版本,请勿在生产环境中使用
|
||||
- ADD: 尝试加入程序内置速率限制
|
||||
- CHANGE: 更新相关依赖库
|
||||
- CHANGE: 更换Dev版本底包,于release版本保持一致
|
||||
|
||||
v1.6.2
|
||||
---
|
||||
|
||||
@@ -1 +1 @@
|
||||
24w21a
|
||||
24w21d
|
||||
37
api/api.go
37
api/api.go
@@ -13,7 +13,6 @@ var (
|
||||
cfg *config.Config
|
||||
)
|
||||
|
||||
// 日志模块
|
||||
var (
|
||||
logw = logger.Logw
|
||||
logInfo = logger.LogInfo
|
||||
@@ -21,8 +20,7 @@ var (
|
||||
logError = logger.LogError
|
||||
)
|
||||
|
||||
func InitHandleRouter(cfg *config.Config, router *gin.Engine) {
|
||||
// 设置路由
|
||||
func InitHandleRouter(cfg *config.Config, router *gin.Engine, version string) {
|
||||
apiRouter := router.Group("api")
|
||||
{
|
||||
apiRouter.GET("/size_limit", func(c *gin.Context) {
|
||||
@@ -40,6 +38,15 @@ func InitHandleRouter(cfg *config.Config, router *gin.Engine) {
|
||||
apiRouter.GET("/healthcheck", func(c *gin.Context) {
|
||||
HealthcheckHandler(c)
|
||||
})
|
||||
apiRouter.GET("/version", func(c *gin.Context) {
|
||||
VersionHandler(c, version)
|
||||
})
|
||||
apiRouter.GET("/rate_limit/status", func(c *gin.Context) {
|
||||
RateLimitStatusHandler(c, cfg)
|
||||
})
|
||||
apiRouter.GET("/rate_limit/limit", func(c *gin.Context) {
|
||||
RateLimitLimitHandler(c, cfg)
|
||||
})
|
||||
}
|
||||
logInfo("API router Init success")
|
||||
}
|
||||
@@ -84,3 +91,27 @@ func HealthcheckHandler(c *gin.Context) {
|
||||
"Status": "OK",
|
||||
})
|
||||
}
|
||||
|
||||
func VersionHandler(c *gin.Context, version string) {
|
||||
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")
|
||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||
"Version": version,
|
||||
})
|
||||
}
|
||||
|
||||
func RateLimitStatusHandler(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")
|
||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||
"RateLimit": cfg.RateLimit.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
func RateLimitLimitHandler(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")
|
||||
json.NewEncoder(c.Writer).Encode(map[string]interface{}{
|
||||
"RatePerMinute": cfg.RateLimit.RatePerMinute,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 日志模块
|
||||
var (
|
||||
logw = logger.Logw
|
||||
logInfo = logger.LogInfo
|
||||
@@ -16,7 +15,6 @@ var (
|
||||
logError = logger.LogError
|
||||
)
|
||||
|
||||
// Auth Init
|
||||
func Init(cfg *config.Config) {
|
||||
if cfg.Blacklist.Enabled {
|
||||
LoadBlacklist(cfg)
|
||||
@@ -28,17 +26,13 @@ func Init(cfg *config.Config) {
|
||||
}
|
||||
|
||||
func AuthHandler(c *gin.Context, cfg *config.Config) (isValid bool, err string) {
|
||||
// 如果身份验证未启用,直接返回 true
|
||||
if !cfg.Auth.Enabled {
|
||||
return true, ""
|
||||
}
|
||||
|
||||
// 获取 auth_token 参数
|
||||
authToken := c.Query("auth_token")
|
||||
// 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
|
||||
if authToken == "" {
|
||||
err := "Auth token == nil"
|
||||
return false, err
|
||||
|
||||
@@ -33,8 +33,8 @@ func LoadBlacklist(cfg *config.Config) {
|
||||
}
|
||||
|
||||
// fullrepo: "owner/repo" or "owner/*"
|
||||
func CheckBlacklist(fullrepo string) bool {
|
||||
return forRangeCheckBlacklist(blacklist.Blacklist, fullrepo)
|
||||
func CheckBlacklist(repouser string, user string, repo string) bool {
|
||||
return forRangeCheckBlacklist(blacklist.Blacklist, repouser, user)
|
||||
}
|
||||
|
||||
func sliceRepoName_Blacklist(fullrepo string) (string, string) {
|
||||
@@ -45,12 +45,29 @@ func sliceRepoName_Blacklist(fullrepo string) (string, string) {
|
||||
return s[0], s[1]
|
||||
}
|
||||
|
||||
func forRangeCheckBlacklist(blist []string, fullrepo string) bool {
|
||||
repoUser, _ := sliceRepoName_Blacklist(fullrepo)
|
||||
func forRangeCheckBlacklist(blist []string, fullrepo string, user string) bool {
|
||||
// 先匹配user,再匹配user/*,最后匹配完整repo
|
||||
for _, blocked := range blist {
|
||||
// 切片
|
||||
users, _ := sliceRepoName_Blacklist(blocked)
|
||||
logw("users:%s, blocked:%s", users, blocked)
|
||||
// 匹配 user
|
||||
if user == users {
|
||||
// 匹配 user/*
|
||||
if strings.HasSuffix(blocked, "/*") {
|
||||
return true
|
||||
}
|
||||
// 匹配完整repo
|
||||
if fullrepo == blocked {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* for _, blocked := range blist {
|
||||
if blocked == fullrepo || (strings.HasSuffix(blocked, "/*") && strings.HasPrefix(repoUser, blocked[:len(blocked)-2])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} */
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -96,7 +96,9 @@ VERSION=$(curl -s https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/mai
|
||||
wget -q -O ${ghproxy_dir}/VERSION https://raw.githubusercontent.com/WJQSERVER-STUDIO/ghproxy/main/DEV-VERSION
|
||||
|
||||
# 下载ghproxy
|
||||
wget -q -O ${ghproxy_dir}/ghproxy https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/$VERSION/ghproxy-linux-$ARCH
|
||||
wget -q -O ${ghproxy_dir}/ghproxy https://github.com/WJQSERVER-STUDIO/ghproxy/releases/download/$VERSION/ghproxy-linux-$ARCH.tar.gz
|
||||
install tar
|
||||
tar -zxvf ${ghproxy_dir}/ghproxy-linux-$ARCH.tar.gz -C ${ghproxy_dir}
|
||||
chmod +x ${ghproxy_dir}/ghproxy
|
||||
|
||||
# 下载pages
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM wjqserver/caddy:daily-alpine AS builder
|
||||
FROM wjqserver/caddy:2.9.0-rc-alpine AS builder
|
||||
|
||||
ARG USER=WJQSERVER-STUDIO
|
||||
ARG REPO=ghproxy
|
||||
@@ -13,7 +13,7 @@ RUN mkdir -p /data/${APPLICATION}/config
|
||||
RUN mkdir -p /data/${APPLICATION}/log
|
||||
|
||||
# 安装依赖
|
||||
RUN apk add --no-cache curl wget
|
||||
RUN apk add --no-cache curl wget tar
|
||||
|
||||
# 前端
|
||||
RUN wget -O /data/www/index.html https://raw.githubusercontent.com/${USER}/${REPO}/main/pages/index.html
|
||||
@@ -21,7 +21,9 @@ RUN wget -O /data/www/favicon.ico 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}-${TARGETOS}-${TARGETARCH}
|
||||
wget -O /data/${APPLICATION}/${APPLICATION}-${TARGETOS}-${TARGETARCH}.tar.gz https://github.com/${USER}/${REPO}/releases/download/$VERSION/${APPLICATION}-${TARGETOS}-${TARGETARCH}.tar.gz && \
|
||||
tar -zxvf /data/${APPLICATION}/${APPLICATION}-${TARGETOS}-${TARGETARCH}.tar.gz -C /data/${APPLICATION} && \
|
||||
rm -rf /data/${APPLICATION}/${APPLICATION}-${TARGETOS}-${TARGETARCH}.tar.gz
|
||||
RUN wget -O /usr/local/bin/init.sh https://raw.githubusercontent.com/${USER}/${REPO}/main/docker/dockerfile/dev/init.sh
|
||||
|
||||
# 拉取配置
|
||||
@@ -34,7 +36,7 @@ RUN wget -O /data/${APPLICATION}/whitelist.json https://raw.githubusercontent.co
|
||||
RUN chmod +x /data/${APPLICATION}/${APPLICATION}
|
||||
RUN chmod +x /usr/local/bin/init.sh
|
||||
|
||||
FROM wjqserver/caddy:daily-alpine
|
||||
FROM wjqserver/caddy:2.9.0-rc-alpine
|
||||
|
||||
COPY --from=builder /data/www /data/www
|
||||
COPY --from=builder /data/caddy /data/caddy
|
||||
|
||||
4
go.mod
4
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/imroc/req/v3 v3.48.0
|
||||
golang.org/x/time v0.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -22,7 +23,7 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
|
||||
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
@@ -48,7 +49,6 @@ require (
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -52,6 +52,8 @@ github.com/google/pprof v0.0.0-20241023014458-598669927662 h1:SKMkD83p7FwUqKmBsP
|
||||
github.com/google/pprof v0.0.0-20241023014458-598669927662/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs=
|
||||
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
||||
@@ -56,7 +56,6 @@ func Log(customMessage string) {
|
||||
logChannel <- customMessage
|
||||
}
|
||||
|
||||
// 格式化日志记录
|
||||
func Logw(format string, args ...interface{}) {
|
||||
message := fmt.Sprintf(format, args...)
|
||||
Log(message)
|
||||
@@ -82,7 +81,6 @@ func LogError(format string, args ...interface{}) {
|
||||
Log(message)
|
||||
}
|
||||
|
||||
// 关闭日志文件
|
||||
func Close() {
|
||||
logFileMutex.Lock()
|
||||
defer logFileMutex.Unlock()
|
||||
|
||||
8
main.go
8
main.go
@@ -23,6 +23,7 @@ var (
|
||||
configfile = "/data/ghproxy/config/config.toml"
|
||||
cfgfile string
|
||||
limiter *rate.RateLimiter
|
||||
version string
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -61,8 +62,8 @@ func loadlist(cfg *config.Config) {
|
||||
auth.Init(cfg)
|
||||
}
|
||||
|
||||
func setupApi(cfg *config.Config, router *gin.Engine) {
|
||||
api.InitHandleRouter(cfg, router)
|
||||
func setupApi(cfg *config.Config, router *gin.Engine, version string) {
|
||||
api.InitHandleRouter(cfg, router, version)
|
||||
}
|
||||
|
||||
func setupRateLimit(cfg *config.Config) {
|
||||
@@ -78,13 +79,14 @@ func init() {
|
||||
loadConfig()
|
||||
setupLogger(cfg)
|
||||
loadlist(cfg)
|
||||
setupRateLimit(cfg)
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
|
||||
router = gin.Default()
|
||||
router.UseH2C = true
|
||||
|
||||
setupApi(cfg, router)
|
||||
setupApi(cfg, router, version)
|
||||
|
||||
if cfg.Pages.Enabled {
|
||||
indexPagePath := fmt.Sprintf("%s/index.html", cfg.Pages.StaticDir)
|
||||
|
||||
111
pages/index.html
111
pages/index.html
@@ -6,12 +6,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Github文件加速">
|
||||
<meta name="keywords" content="Github,文件加速,ghproxy">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<title>Github文件加速</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://font.sec.miui.com/font/css?family=MiSans:400,700:MiSans">
|
||||
<style>
|
||||
|
||||
:root {
|
||||
--color: #dadada;
|
||||
--fontcolor: #333;
|
||||
@@ -41,6 +40,35 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.version {
|
||||
width: 12.5%;
|
||||
height: 2%;
|
||||
background-color: #39c5bb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 0.8rem;
|
||||
border-radius: 0.5rem;
|
||||
position: fixed;
|
||||
bottom: 0%;
|
||||
right: 0%;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background: #39c5bb;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 80%;
|
||||
text-align: center;
|
||||
@@ -89,9 +117,9 @@
|
||||
pre {
|
||||
background: #012333;
|
||||
color: #39c5bc;
|
||||
padding: 20px 20px;
|
||||
margin: 10px 0;
|
||||
border-radius: 8px;
|
||||
padding: 15px 20px 15px 20px;
|
||||
margin: 0px 0;
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
}
|
||||
@@ -100,10 +128,10 @@
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #bd3c35;
|
||||
border-radius: 50%;
|
||||
box-shadow: 20px 0 0 #d69f27, 40px 0 0 #39c5bb;
|
||||
@@ -111,7 +139,8 @@
|
||||
|
||||
code {
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 1em;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -158,9 +187,14 @@
|
||||
.status-container {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 10%;
|
||||
}
|
||||
|
||||
.version {
|
||||
width: 7.5%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-group {
|
||||
@@ -201,7 +235,7 @@
|
||||
|
||||
.copy-button {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background: rgba(0, 217, 224, 0.822);
|
||||
color: white;
|
||||
@@ -211,6 +245,24 @@
|
||||
cursor: pointer;
|
||||
transition: opacity 0.3s;
|
||||
z-index: 1;
|
||||
font-size: 0.85rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.redir-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 65px;
|
||||
background: rgba(0, 217, 224, 0.822);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.3s;
|
||||
z-index: 1;
|
||||
font-size: 0.85rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre:hover .copy-button {
|
||||
@@ -239,6 +291,9 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="version">
|
||||
<p id="version"></p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1>Github文件加速</h1>
|
||||
<div class="form-group">
|
||||
@@ -248,6 +303,7 @@
|
||||
|
||||
<div class="code" id="outputBlock">
|
||||
<button class="copy-button" id="copyButton">复制</button>
|
||||
<button class="redir-button" id="redirButton">打开</button>
|
||||
<pre id="formattedLinkOutput"></pre>
|
||||
</div>
|
||||
<div class="tips">
|
||||
@@ -274,16 +330,22 @@
|
||||
|
||||
if (githubLinkInput.value.startsWith("https://github.com/") || githubLinkInput.value.startsWith("http://github.com/")) {
|
||||
formattedLink = "https://" + currentHost + "/github.com" + githubLinkInput.value.substring(githubLinkInput.value.indexOf("/", 8));
|
||||
displayButton();
|
||||
} else if (githubLinkInput.value.startsWith("github.com/")) {
|
||||
formattedLink = "https://" + currentHost + "/" + githubLinkInput.value;
|
||||
displayButton();
|
||||
} else if (githubLinkInput.value.startsWith("https://raw.githubusercontent.com/") || githubLinkInput.value.startsWith("http://raw.githubusercontent.com/")) {
|
||||
formattedLink = "https://" + currentHost + githubLinkInput.value.substring(githubLinkInput.value.indexOf("/", 7));
|
||||
displayButton();
|
||||
} else if (githubLinkInput.value.startsWith("raw.githubusercontent.com/")) {
|
||||
formattedLink = "https://" + currentHost + "/" + githubLinkInput.value;
|
||||
displayButton();
|
||||
} else if (githubLinkInput.value.startsWith("https://gist.githubusercontent.com/") || githubLinkInput.value.startsWith("http://gist.githubusercontent.com/")) {
|
||||
formattedLink = "https://" + currentHost + "/gist.github.com" + githubLinkInput.value.substring(githubLinkInput.value.indexOf("/", 18));
|
||||
displayButton();
|
||||
} else if (githubLinkInput.value.startsWith("gist.githubusercontent.com/")) {
|
||||
formattedLink = "https://" + currentHost + "/" + githubLinkInput.value;
|
||||
displayButton();
|
||||
} else {
|
||||
showToast('请输入有效的GitHub链接');
|
||||
}
|
||||
@@ -291,6 +353,19 @@
|
||||
formattedLinkOutput.textContent = formattedLink;
|
||||
}
|
||||
|
||||
function displayButton() {
|
||||
var copyButton = document.getElementById('copyButton');
|
||||
var redirButton = document.getElementById('redirButton');
|
||||
copyButton.style.display = 'block';
|
||||
redirButton.style.display = 'block';
|
||||
}
|
||||
|
||||
function redirToFormattedLink() {
|
||||
var formattedLinkOutput = document.getElementById('formattedLinkOutput');
|
||||
console.log(formattedLinkOutput.textContent);
|
||||
window.open(formattedLinkOutput.textContent);
|
||||
}
|
||||
|
||||
document.getElementById('formatButton').addEventListener('click', formatGithubLink);
|
||||
document.getElementById('copyButton').addEventListener('click', function () {
|
||||
const output = document.getElementById('formattedLinkOutput');
|
||||
@@ -300,9 +375,9 @@
|
||||
window.getSelection().addRange(range);
|
||||
document.execCommand('copy');
|
||||
window.getSelection().removeAllRanges();
|
||||
//alert('链接已复制到剪贴板');
|
||||
showToast('链接已复制到剪贴板');
|
||||
});
|
||||
document.getElementById('redirButton').addEventListener('click', redirToFormattedLink);
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.getElementById('toast');
|
||||
@@ -360,10 +435,22 @@
|
||||
console.error('Error fetching API:', error);
|
||||
});
|
||||
}
|
||||
function fetchVersion() {
|
||||
fetch(window.location.origin + '/api/version')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const version = document.getElementById('version');
|
||||
version.textContent = `${data.Version}`;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching API:', error);
|
||||
});
|
||||
}
|
||||
function fetchAPI() {
|
||||
fetchSizeLimit();
|
||||
fetchWhiteList();
|
||||
fetchBlackList();
|
||||
fetchVersion();
|
||||
}
|
||||
document.addEventListener('DOMContentLoaded', fetchAPI);
|
||||
</script>
|
||||
|
||||
@@ -60,14 +60,14 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter) gin.HandlerFu
|
||||
username, repo := MatchUserRepo(rawPath, cfg, c, matches)
|
||||
|
||||
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)
|
||||
repouser := fmt.Sprintf("%s/%s", username, repo)
|
||||
|
||||
// 白名单检查
|
||||
if cfg.Whitelist.Enabled {
|
||||
whitelist := auth.CheckWhitelist(fullrepo)
|
||||
whitelist := auth.CheckWhitelist(repouser)
|
||||
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)
|
||||
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, repouser)
|
||||
errMsg := fmt.Sprintf("Whitelist Blocked repo: %s", repouser)
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
||||
logWarning(logErrMsg)
|
||||
return
|
||||
@@ -76,10 +76,10 @@ func NoRouteHandler(cfg *config.Config, limiter *rate.RateLimiter) gin.HandlerFu
|
||||
|
||||
// 黑名单检查
|
||||
if cfg.Blacklist.Enabled {
|
||||
blacklist := auth.CheckBlacklist(fullrepo)
|
||||
blacklist := auth.CheckBlacklist(repouser, username, repo)
|
||||
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)
|
||||
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, repouser)
|
||||
errMsg := fmt.Sprintf("Blacklist Blocked repo: %s", repouser)
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": errMsg})
|
||||
logWarning(logErrMsg)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user