Something went wrong. Try again.
some kind of github proxy
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103package proxy
import ( "embed" "net/http" "strings"
"code.wejust.rest/lain/ghproxy/internal/config" "github.com/gin-gonic/gin")
//go:embed static/index.htmlvar staticFS embed.FS
type ProxyHandler struct { addr string githubProxy http.Handler assetsProxy http.Handler apiProxy http.Handler allowedRepos map[string]bool}
func NewProxyHandler(cfg *config.Config) (*ProxyHandler, error) { allowed := make(map[string]bool) for _, repo := range cfg.AllowedRepos { allowed[repo] = true }
return &ProxyHandler{ addr: cfg.Addr, githubProxy: CreateReverseProxy("https://github.com"), assetsProxy: CreateReverseProxy("https://github.githubassets.com"), apiProxy: CreateReverseProxy("https://api.github.com"), allowedRepos: allowed, }, nil}
func (h *ProxyHandler) RegisterRoutes(r *gin.Engine) { r.GET("/", func(c *gin.Context) { if c.Request.URL.Path == "/" { data, err := staticFS.ReadFile("static/index.html") if err != nil { c.String(http.StatusInternalServerError, "failed to read embedded index.html") return } c.Data(http.StatusOK, "text/html; charset=utf-8", data) return } c.Next() })
r.GET("/robots.txt", func(c *gin.Context) { c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte("User-Agent: *\nDisallow: /\n")) })
r.NoRoute(func(c *gin.Context) { reqPath := c.Request.URL.Path
if strings.Contains(reqPath, "/_private/browser/stats") { c.AbortWithStatus(http.StatusNoContent) return }
//NOTE(kroot): proxy GitHub GraphQL API as-is to avoid breaking the issues UI if reqPath == "/_graphql" { h.githubProxy.ServeHTTP(c.Writer, c.Request) return }
//NOTE(kroot): handle assets, gravatars, and favicons if strings.Contains(reqPath, "/assets/") || strings.HasPrefix(reqPath, "/images/gravatars/") || strings.HasPrefix(reqPath, "/favicons/") { h.assetsProxy.ServeHTTP(c.Writer, c.Request) return }
if strings.HasPrefix(reqPath, "/api/") { //NOTE(kroot): strip /api prefix if needed, or just proxy as is h.apiProxy.ServeHTTP(c.Writer, c.Request) return }
parts := strings.Split(strings.Trim(reqPath, "/"), "/")
//NOTE(kroot): if we have allowed_repos, restrict access if len(h.allowedRepos) > 0 { if len(parts) >= 2 { repoFullName := parts[0] + "/" + parts[1] if h.allowedRepos[repoFullName] { h.serveWithCache(c.Writer, c.Request, h.githubProxy) return } }
//NOTE(kroot): if its not an allowed repository, and allowed_repos is not empty, just redirect to root c.Redirect(http.StatusSeeOther, "/") return }
//NOTE(kroot): if allowed_repos is empty, allow everything h.serveWithCache(c.Writer, c.Request, h.githubProxy) })}