QSLY commited on
Commit
c3a1b3c
·
verified ·
1 Parent(s): 1382143

Upload 10 files

Browse files
Files changed (10) hide show
  1. .gitattributes +2 -35
  2. .gitignore +4 -0
  3. Dockerfile +50 -0
  4. README.md +18 -10
  5. config.json +18 -0
  6. config.json.dist +18 -0
  7. docker-entrypoint.sh +31 -0
  8. go.mod +34 -0
  9. go.sum +89 -0
  10. main.go +260 -0
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+
2
+ /.idea
3
+ buiid.bat
4
+ main_linux
Dockerfile ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM golang:1.22-alpine AS builder
2
+ RUN go env -w GO111MODULE=auto \
3
+ && go env -w CGO_ENABLED=0
4
+ # && go env -w GOPROXY=https://goproxy.cn,direct
5
+
6
+ WORKDIR /build
7
+
8
+ COPY ./ .
9
+
10
+ RUN set -ex \
11
+ && cd /build \
12
+ && go build -ldflags "-s -w -extldflags '-static'" -o gh-proxy
13
+
14
+ FROM alpine:latest
15
+
16
+ COPY docker-entrypoint.sh /docker-entrypoint.sh
17
+
18
+ RUN chmod +x /docker-entrypoint.sh && \
19
+ apk add --no-cache --update \
20
+ coreutils \
21
+ shadow \
22
+ su-exec \
23
+ tzdata && \
24
+ rm -rf /var/cache/apk/* && \
25
+ mkdir -p /app && \
26
+ mkdir -p /config && \
27
+ useradd -d /config -s /bin/sh abc && \
28
+ chown -R abc /config
29
+
30
+ ENV TZ="Asia/Shanghai"
31
+ ENV UID=99
32
+ ENV GID=100
33
+ ENV UMASK=002
34
+ ENV WHITE_LIST=""
35
+ ENV BLACK_LIST="\"example3\",\"example4\""
36
+ ENV ALLOW_PROXY_ALL="false"
37
+ ENV OTHER_WHITE_LIST=""
38
+ ENV OTHER_BLACK_LIST="\"example3\",\"example4\""
39
+ ENV HTTP_HOST=""
40
+ ENV HTTP_PORT="8080"
41
+ ENV SIZE_LIMIT="10737418240"
42
+
43
+ COPY --from=builder /build/gh-proxy /app/
44
+ COPY --from=builder /build/config.json.dist /app/
45
+
46
+ WORKDIR /app
47
+
48
+ VOLUME [ "/app" ]
49
+
50
+ ENTRYPOINT [ "/docker-entrypoint.sh" ]
README.md CHANGED
@@ -1,12 +1,20 @@
1
- ---
2
- title: Ghp
3
- emoji: 🔥
4
- colorFrom: purple
5
- colorTo: red
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- short_description: ghproxy
 
 
 
 
 
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # gh-proxy-go
2
+
3
+ 这是 [gh-proxy](https://github.com/hunshcn/gh-proxy) 的 Go 语言版本。
4
+
5
+ ## 部署详情
6
+
7
+ [github.moeyy.xyz](https://github.moeyy.xyz/) 正在使用 **gh-proxy-go**,托管在 [BuyVM](https://buyvm.net/) 每月 3.5 美元的 1 核 1G 内存、10Gbps 带宽服务器上。
8
+
9
+ ### 服务器概况:
10
+
11
+ - **日流量处理**:约 3TB
12
+ - **CPU 平均使用率**:20%
13
+ - **带宽平均占用**:400Mbps
14
+
15
+ ![服务器数据](https://github.com/user-attachments/assets/6fe37f41-aa35-4efc-b0b8-8c3339529326)
16
+ ![Cloudflare 数据](https://github.com/user-attachments/assets/ae310b1f-96e9-42e9-a77c-0d8c1b8d6344)
17
+
18
  ---
19
 
20
+ 如有问题或改进建议,欢迎提交 issue PR!
config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "host": "0.0.0.0",
3
+ "port": 8080,
4
+ "sizeLimit": 10737418240,
5
+ "whiteList": [
6
+ ],
7
+ "blackList": [
8
+ "example3",
9
+ "example4"
10
+ ],
11
+ "AllowProxyAll": false,
12
+ "otherWhiteList": [
13
+ ],
14
+ "otherBlackList": [
15
+ "example3",
16
+ "example4"
17
+ ]
18
+ }
config.json.dist ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "host": "%HTTP_HOST%",
3
+ "port": %HTTP_PORT%,
4
+ "sizeLimit": %SIZE_LIMIT%,
5
+ "whiteList": [
6
+ %WHITE_LIST%
7
+ ],
8
+ "blackList": [
9
+ %BLACK_LIST%
10
+ ],
11
+ "AllowProxyAll": %ALLOW_PROXY_ALL%,
12
+ "otherWhiteList": [
13
+ %OTHER_WHITE_LIST%
14
+ ],
15
+ "otherBlackList": [
16
+ %OTHER_BLACK_LIST%
17
+ ]
18
+ }
docker-entrypoint.sh ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ USER=abc
4
+
5
+ echo "---Setup Timezone to ${TZ}---"
6
+ echo "${TZ}" > /etc/timezone
7
+ echo "---Checking if UID: ${UID} matches user---"
8
+ usermod -o -u ${UID} ${USER}
9
+ echo "---Checking if GID: ${GID} matches user---"
10
+ groupmod -o -g ${GID} ${USER} > /dev/null 2>&1 ||:
11
+ usermod -g ${GID} ${USER}
12
+ echo "---Setting umask to ${UMASK}---"
13
+ umask ${UMASK}
14
+
15
+ echo "---Taking ownership of data...---"
16
+ chown -R ${UID}:${GID} /app /data
17
+ chmod +x /app/gh-proxy
18
+
19
+ echo "make config"
20
+ cp /app/config.json.dist /app/config.json
21
+ sed -i "s|%WHITE_LIST%|$WHITE_LIST|g" /app/config.json
22
+ sed -i "s|%BLACK_LIST%|$BLACK_LIST|g" /app/config.json
23
+ sed -i "s|%ALLOW_PROXY_ALL%|$ALLOW_PROXY_ALL|g" /app/config.json
24
+ sed -i "s|%OTHER_WHITE_LIST%|$OTHER_WHITE_LIST|g" /app/config.json
25
+ sed -i "s|%OTHER_BLACK_LIST%|$OTHER_BLACK_LIST|g" /app/config.json
26
+ sed -i "s|%HTTP_HOST%|$HTTP_HOST|g" /app/config.json
27
+ sed -i "s|%HTTP_PORT%|$HTTP_PORT|g" /app/config.json
28
+ sed -i "s|%SIZE_LIMIT%|$SIZE_LIMIT|g" /app/config.json
29
+
30
+ echo "Starting..."
31
+ su-exec ${USER} /app/gh-proxy "$@"
go.mod ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module gh-proxy-go
2
+
3
+ go 1.22.5
4
+
5
+ require github.com/gin-gonic/gin v1.10.0
6
+
7
+ require (
8
+ github.com/bytedance/sonic v1.11.6 // indirect
9
+ github.com/bytedance/sonic/loader v0.1.1 // indirect
10
+ github.com/cloudwego/base64x v0.1.4 // indirect
11
+ github.com/cloudwego/iasm v0.2.0 // indirect
12
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
13
+ github.com/gin-contrib/sse v0.1.0 // indirect
14
+ github.com/go-playground/locales v0.14.1 // indirect
15
+ github.com/go-playground/universal-translator v0.18.1 // indirect
16
+ github.com/go-playground/validator/v10 v10.20.0 // indirect
17
+ github.com/goccy/go-json v0.10.2 // indirect
18
+ github.com/json-iterator/go v1.1.12 // indirect
19
+ github.com/klauspost/cpuid/v2 v2.2.7 // indirect
20
+ github.com/leodido/go-urn v1.4.0 // indirect
21
+ github.com/mattn/go-isatty v0.0.20 // indirect
22
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
23
+ github.com/modern-go/reflect2 v1.0.2 // indirect
24
+ github.com/pelletier/go-toml/v2 v2.2.2 // indirect
25
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
26
+ github.com/ugorji/go/codec v1.2.12 // indirect
27
+ golang.org/x/arch v0.8.0 // indirect
28
+ golang.org/x/crypto v0.23.0 // indirect
29
+ golang.org/x/net v0.25.0 // indirect
30
+ golang.org/x/sys v0.20.0 // indirect
31
+ golang.org/x/text v0.15.0 // indirect
32
+ google.golang.org/protobuf v1.34.1 // indirect
33
+ gopkg.in/yaml.v3 v3.0.1 // indirect
34
+ )
go.sum ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
2
+ github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
3
+ github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
4
+ github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
5
+ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
6
+ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
7
+ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
8
+ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
9
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
11
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12
+ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
13
+ github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
14
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
15
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
16
+ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
17
+ github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
18
+ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
19
+ github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
20
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
21
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
22
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
23
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
24
+ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
25
+ github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
26
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
27
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
28
+ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
29
+ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
30
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
31
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
32
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
33
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
34
+ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
35
+ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
36
+ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
37
+ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
38
+ github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
39
+ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
40
+ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
41
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
42
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
43
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
44
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
45
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
46
+ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
47
+ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
48
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
49
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
50
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
51
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
52
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
53
+ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
54
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
55
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
56
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
57
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
58
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
59
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
60
+ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
61
+ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
62
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
63
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
64
+ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
65
+ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
66
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
67
+ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
68
+ golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
69
+ golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
70
+ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
71
+ golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
72
+ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
73
+ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
74
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
75
+ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
76
+ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
77
+ golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
78
+ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
79
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
80
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
81
+ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
82
+ google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
83
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
84
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
85
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
86
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
87
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
88
+ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
89
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
main.go ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "embed"
5
+ "encoding/json"
6
+ "fmt"
7
+ "github.com/gin-gonic/gin"
8
+ "io"
9
+ "io/fs"
10
+ "net"
11
+ "net/http"
12
+ "os"
13
+ "regexp"
14
+ "strconv"
15
+ "strings"
16
+ "sync"
17
+ "time"
18
+ )
19
+
20
+ const (
21
+ sizeLimit int64 = 1024 * 1024 * 1024 * 10 // 允许的文件大小,默认10GB
22
+ host = "0.0.0.0" // 监听地址
23
+ port = 8080 // 监听端口
24
+ )
25
+
26
+ //go:embed public/*
27
+ var public embed.FS
28
+
29
+ var (
30
+ exps = []*regexp.Regexp{
31
+ regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:releases|archive)/.*$`),
32
+ regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:blob|raw)/.*$`),
33
+ regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:info|git-).*$`),
34
+ regexp.MustCompile(`^(?:https?://)?raw\.github(?:usercontent|)\.com/([^/]+)/([^/]+)/.+?/.+$`),
35
+ regexp.MustCompile(`^(?:https?://)?gist\.github\.com/([^/]+)/.+?/.+$`),
36
+ }
37
+ httpClient *http.Client
38
+ config *Config
39
+ configLock sync.RWMutex
40
+ )
41
+
42
+ type Config struct {
43
+ Host string `json:"host"`
44
+ Port int64 `json:"port"`
45
+ SizeLimit int64 `json:"sizeLimit"`
46
+ WhiteList []string `json:"whiteList"`
47
+ BlackList []string `json:"blackList"`
48
+ AllowProxyAll bool `json:"allowProxyAll"` // 是否允许代理非github的其他地址
49
+ OtherWhiteList []string `json:"otherWhiteList"`
50
+ OtherBlackList []string `json:"otherBlackList"`
51
+ }
52
+
53
+ func main() {
54
+ gin.SetMode(gin.ReleaseMode)
55
+ router := gin.Default()
56
+
57
+ httpClient = &http.Client{
58
+ Transport: &http.Transport{
59
+ DialContext: (&net.Dialer{
60
+ Timeout: 30 * time.Second,
61
+ KeepAlive: 30 * time.Second,
62
+ }).DialContext,
63
+ MaxIdleConns: 1000,
64
+ MaxIdleConnsPerHost: 1000,
65
+ IdleConnTimeout: 90 * time.Second,
66
+ TLSHandshakeTimeout: 10 * time.Second,
67
+ ExpectContinueTimeout: 1 * time.Second,
68
+ ResponseHeaderTimeout: 300 * time.Second,
69
+ },
70
+ }
71
+
72
+ loadConfig()
73
+ go func() {
74
+ for {
75
+ time.Sleep(10 * time.Minute)
76
+ loadConfig()
77
+ }
78
+ }()
79
+ // if config.Host==""{
80
+ // config.Host=host
81
+ // }
82
+ if config.Port == 0 {
83
+ config.Port = port
84
+ }
85
+ if config.SizeLimit <= 0 {
86
+ config.SizeLimit = sizeLimit
87
+ }
88
+ // 修改静态文件服务方式
89
+ subFS, err := fs.Sub(public, "public")
90
+ if err != nil {
91
+ panic(fmt.Sprintf("无法创建子文件系统: %v", err))
92
+ }
93
+
94
+ // 使用 StaticFS 提供静态文件
95
+ router.StaticFS("/", http.FS(subFS))
96
+ // router.StaticFile("/", "./public/index.html")
97
+ // router.StaticFile("/favicon.ico", "./public/favicon.ico")
98
+ // router.StaticFile("/logo.png", "./public/logo.png")
99
+ router.NoRoute(handler)
100
+ fmt.Printf("starting http server on %s:%d \n", config.Host, config.Port)
101
+ err = router.Run(fmt.Sprintf("%s:%d", config.Host, config.Port))
102
+ if err != nil {
103
+ fmt.Printf("Error starting server: %v\n", err)
104
+ }
105
+ }
106
+
107
+ func handler(c *gin.Context) {
108
+ rawPath := strings.TrimPrefix(c.Request.URL.RequestURI(), "/")
109
+
110
+ for strings.HasPrefix(rawPath, "/") {
111
+ rawPath = strings.TrimPrefix(rawPath, "/")
112
+ }
113
+
114
+ if !strings.HasPrefix(rawPath, "http") {
115
+ // c.String(http.StatusForbidden, "Invalid input.")
116
+ // return
117
+ rawPath = fmt.Sprintf("https://%s", rawPath)
118
+ }
119
+
120
+ matches := checkURL(rawPath)
121
+ if matches != nil {
122
+ if len(config.WhiteList) > 0 && !checkList(matches, config.WhiteList) {
123
+ c.String(http.StatusForbidden, "Forbidden by white list.")
124
+ return
125
+ }
126
+ if len(config.BlackList) > 0 && checkList(matches, config.BlackList) {
127
+ c.String(http.StatusForbidden, "Forbidden by black list.")
128
+ return
129
+ }
130
+ } else {
131
+ if !config.AllowProxyAll {
132
+ c.String(http.StatusForbidden, "Invalid input.")
133
+ return
134
+ }
135
+ if len(config.OtherWhiteList) > 0 && !checkOhterList(rawPath, config.OtherWhiteList) {
136
+ c.String(http.StatusForbidden, "Forbidden by white list.")
137
+ return
138
+ }
139
+ if len(config.OtherBlackList) > 0 && checkOhterList(rawPath, config.OtherBlackList) {
140
+ c.String(http.StatusForbidden, "Forbidden by black list.")
141
+ return
142
+ }
143
+ }
144
+
145
+ if exps[1].MatchString(rawPath) {
146
+ rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
147
+ }
148
+
149
+ proxy(c, rawPath)
150
+ }
151
+
152
+ func proxy(c *gin.Context, u string) {
153
+ req, err := http.NewRequest(c.Request.Method, u, c.Request.Body)
154
+ if err != nil {
155
+ c.String(http.StatusInternalServerError, fmt.Sprintf("server error %v", err))
156
+ return
157
+ }
158
+
159
+ for key, values := range c.Request.Header {
160
+ for _, value := range values {
161
+ req.Header.Add(key, value)
162
+ }
163
+ }
164
+ req.Header.Del("Host")
165
+
166
+ resp, err := httpClient.Do(req)
167
+ if err != nil {
168
+ c.String(http.StatusInternalServerError, fmt.Sprintf("server error %v", err))
169
+ return
170
+ }
171
+ defer func(Body io.ReadCloser) {
172
+ err := Body.Close()
173
+ if err != nil {
174
+
175
+ }
176
+ }(resp.Body)
177
+
178
+ if contentLength, ok := resp.Header["Content-Length"]; ok {
179
+ if size, err := strconv.ParseInt(contentLength[0], 10, 64); err == nil && size > config.SizeLimit {
180
+ c.String(http.StatusRequestEntityTooLarge, "File too large.")
181
+ return
182
+ }
183
+ }
184
+
185
+ resp.Header.Del("Content-Security-Policy")
186
+ resp.Header.Del("Referrer-Policy")
187
+ resp.Header.Del("Strict-Transport-Security")
188
+
189
+ for key, values := range resp.Header {
190
+ for _, value := range values {
191
+ c.Header(key, value)
192
+ }
193
+ }
194
+
195
+ if location := resp.Header.Get("Location"); location != "" {
196
+ if checkURL(location) != nil {
197
+ c.Header("Location", "/"+location)
198
+ } else {
199
+ proxy(c, location)
200
+ return
201
+ }
202
+ }
203
+
204
+ c.Status(resp.StatusCode)
205
+ if _, err := io.Copy(c.Writer, resp.Body); err != nil {
206
+ return
207
+ }
208
+ }
209
+
210
+ func loadConfig() {
211
+ file, err := os.Open("config.json")
212
+ if err != nil {
213
+ fmt.Printf("Error loading config: %v\n", err)
214
+ return
215
+ }
216
+ defer func(file *os.File) {
217
+ err := file.Close()
218
+ if err != nil {
219
+
220
+ }
221
+ }(file)
222
+
223
+ var newConfig Config
224
+ decoder := json.NewDecoder(file)
225
+ if err := decoder.Decode(&newConfig); err != nil {
226
+ fmt.Printf("Error decoding config: %v\n", err)
227
+ return
228
+ }
229
+
230
+ configLock.Lock()
231
+ config = &newConfig
232
+ configLock.Unlock()
233
+ }
234
+
235
+ func checkURL(u string) []string {
236
+ for _, exp := range exps {
237
+ if matches := exp.FindStringSubmatch(u); matches != nil {
238
+ return matches[1:]
239
+ }
240
+ }
241
+ return nil
242
+ }
243
+
244
+ func checkList(matches, list []string) bool {
245
+ for _, item := range list {
246
+ if strings.HasPrefix(matches[0], item) {
247
+ return true
248
+ }
249
+ }
250
+ return false
251
+ }
252
+
253
+ func checkOhterList(url string, list []string) bool {
254
+ for _, item := range list {
255
+ if strings.Contains(url, item) {
256
+ return true
257
+ }
258
+ }
259
+ return false
260
+ }