From b8bce433548600f77359ee8149daef56e0cb4eeb Mon Sep 17 00:00:00 2001 From: fghwett <1058178245@qq.com> Date: Tue, 8 Mar 2022 15:08:20 +0800 Subject: [PATCH] gravatar reverse proxy test --- main.go | 128 ++++++-------------------------------------------------- 1 file changed, 13 insertions(+), 115 deletions(-) diff --git a/main.go b/main.go index 52e5574..9b2c869 100644 --- a/main.go +++ b/main.go @@ -3,126 +3,24 @@ package main import ( "fmt" "net/http" - "regexp" - "strings" + "net/http/httputil" + "net/url" ) -const ( - PREFIX = "/" - - exp1 = `^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:releases|archive)\/.*$` - exp2 = `^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:blob|raw)\/.*$` - exp3 = `^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:info|git-).*$` - exp4 = `^(?:https?:\/\/)?raw\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+?\/.+$` - exp5 = `^(?:https?:\/\/)?gist\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+$` - exp6 = `^(?:https?:\/\/)?github\.com\/.+?\/.+?\/tags.*$` -) - -func checkUrl(u string) bool { - for _, exp := range []string{exp1, exp2, exp3, exp4, exp5, exp6} { - if ok, _ := regexp.MatchString(exp, u); ok { - return true - } - } - return false -} - func fetchHandler(w http.ResponseWriter, r *http.Request) { path := r.URL.Path - if !strings.Contains(path, "/") { - w.WriteHeader(http.StatusNotFound) - return + + path = fmt.Sprintf("https://gravatar.com%s", path) + + rpURL, _ := url.Parse(path) + + proxy := httputil.NewSingleHostReverseProxy(rpURL) + director := proxy.Director + proxy.Director = func(r *http.Request) { + director(r) + r.Host = "gravatar.com" } - - path = strings.TrimPrefix(path, "/") // 获取到的URL - path = strings.Replace(path, "https:/", "https://", 1) - - match1, _ := regexp.MatchString(exp1, path) - match2, _ := regexp.MatchString(exp2, path) - match3, _ := regexp.MatchString(exp3, path) - match4, _ := regexp.MatchString(exp4, path) - match5, _ := regexp.MatchString(exp5, path) - match6, _ := regexp.MatchString(exp6, path) - - if match1 || match5 || match6 || match3 || match4 { - httpHandler(w, r, path) - return - } else if match2 { - path = strings.ReplaceAll(path, "/blob/", "/raw/") - httpHandler(w, r, path) - return - } - - http.Error(w, fmt.Sprintf("%s is not support", path), http.StatusOK) -} - -func httpHandler(w http.ResponseWriter, r *http.Request, pathname string) { - fmt.Println("Handle: ", pathname) - reqHdrRaw := r.Header - - if r.Method == http.MethodOptions && reqHdrRaw.Get("Access-Control-Request-Headers") != "" { - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, TRACE, DELETE, HEAD, OPTIONS") - w.Header().Set("Access-Control-Max-Age", "1728000") - w.WriteHeader(http.StatusNoContent) - return - } - - if strings.HasPrefix(pathname, "github") { - pathname = "https://" + pathname - } - - client := &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - }, - } - - proxy(w, r, client, pathname) -} - -func proxy(w http.ResponseWriter, r *http.Request, client *http.Client, pathname string) { - fmt.Println("Proxy: ", pathname, "Method: ", r.Method) - req, _ := http.NewRequest(r.Method, pathname, r.Body) - for k, v := range r.Header { - req.Header.Set(k, strings.Join(v, ",")) - fmt.Println("Header: ", k, ":", strings.Join(v, ",")) - } - res, e := client.Do(req) - if e != nil { - fmt.Println("Proxy Error: ", pathname, e) - http.Error(w, e.Error(), http.StatusOK) - return - } - - if res.Header.Get("Location") != "" { - location := res.Header.Get("Location") - fmt.Println("Location: ", location) - - if checkUrl(location) { - res.Header.Set("Location", PREFIX+location) - } else { - newReq, _ := http.NewRequest(r.Method, location, res.Body) - client.CheckRedirect = nil - proxy(w, newReq, client, location) - return - } - } - - res.Header.Set("Access-Control-Expose-Headers", "*") - res.Header.Set("Access-Control-Allow-Origin", "*") - - res.Header.Del("Content-Security-Policy") - res.Header.Del("Content-Security-Policy-Report-Only") - res.Header.Del("Clear-Site-Data") - - for k, v := range res.Header { - w.Header().Set(k, strings.Join(v, ",")) - } - if err := res.Write(w); err != nil { - fmt.Println("Write Response Error: ", pathname, err) - } - fmt.Println("result: ", res.StatusCode) + proxy.ServeHTTP(w, r) } func main() {