分享Go语言实现的GitHub.com加速及nginx配置
编译Go项目后,默认端口8080
使用方法如下,假设你的域名是x.com
, 那么你拉取项目的时候就可以参考如下...
git clone https://x.com/github.com/user/info.git
git clone https://x.com/https://github.com/user/info.git
https://x.com/github.com/user/info/blob/main/demo.txt
https://x.com/https://github.com/user/info/blob/main/demo.txt
以下是Nginx反代配置
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
main.go源码
package main
import (
"fmt"
"io"
"net/http"
"regexp"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
const (
sizeLimit = 1024 * 1024 * 1024 * 1
host = "127.0.0.1"
port = 8080
)
var (
exps = []*regexp.Regexp{
regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:releases|archive)/.*$`),
regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:blob|raw)/.*$`),
regexp.MustCompile(`^(?:https?://)?github\.com/([^/]+)/([^/]+)/(?:info|git-).*$`),
regexp.MustCompile(`^(?:https?://)?raw\.github(?:usercontent|)\.com/([^/]+)/([^/]+)/.+?/.+$`),
regexp.MustCompile(`^(?:https?://)?gist\.github\.com/([^/]+)/.+?/.+$`),
}
)
func main() {
gin.SetMode(gin.ReleaseMode)
router := gin.Default()
// 根路径重定向到自己的主站
router.GET("/", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://lvtao.net")
})
router.NoRoute(handler)
err := router.Run(fmt.Sprintf("%s:%d", host, port))
if err != nil {
fmt.Printf("Error starting server: %v\n", err)
}
}
func handler(c *gin.Context) {
rawPath := strings.TrimPrefix(c.Request.URL.RequestURI(), "/")
re := regexp.MustCompile(`^(http:|https:)?/?/?(.*)`)
matches := re.FindStringSubmatch(rawPath)
rawPath = "https://" + matches[2]
matches = checkURL(rawPath)
if matches == nil {
c.String(http.StatusForbidden, "Invalid input.")
return
}
if exps[1].MatchString(rawPath) {
rawPath = strings.Replace(rawPath, "/blob/", "/raw/", 1)
}
proxy(c, rawPath)
}
func proxy(c *gin.Context, u string) {
req, err := http.NewRequest(c.Request.Method, u, c.Request.Body)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("server error %v", err))
return
}
for key, values := range c.Request.Header {
for _, value := range values {
req.Header.Add(key, value)
}
}
req.Header.Del("Host")
resp, err := http.DefaultClient.Do(req)
if err != nil {
c.String(http.StatusInternalServerError, fmt.Sprintf("server error %v", err))
return
}
defer resp.Body.Close()
if contentLength, ok := resp.Header["Content-Length"]; ok {
if size, err := strconv.Atoi(contentLength[0]); err == nil && size > sizeLimit {
finalURL := resp.Request.URL.String()
c.Redirect(http.StatusMovedPermanently, finalURL)
return
}
}
resp.Header.Del("Content-Security-Policy")
resp.Header.Del("Referrer-Policy")
resp.Header.Del("Strict-Transport-Security")
for key, values := range resp.Header {
for _, value := range values {
c.Header(key, value)
}
}
c.Status(resp.StatusCode)
if _, err := io.Copy(c.Writer, resp.Body); err != nil {
return
}
}
func checkURL(u string) []string {
for _, exp := range exps {
if matches := exp.FindStringSubmatch(u); matches != nil {
return matches[1:]
}
}
return nil
}
版权声明:本文为原创文章,版权归 全栈开发技术博客 所有。
本文链接:https://www.lvtao.net/dev/go-nginx-proxy-github.html
转载时须注明出处及本声明