package main import ( "bytes" "compress/gzip" "errors" "flag" "fmt" "io" "io/ioutil" "net/http" "net/http/httputil" "net/url" "os" "strings" "codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-menu/v2/menu" log "github.com/sirupsen/logrus" ) var ( updatedMenu, updatedStringbody string proxyURL, codefirstURL string debug, dump bool ) func gUnzipData(data []byte) (resData []byte, err error) { b := bytes.NewBuffer(data) var r io.Reader r, err = gzip.NewReader(b) if err != nil { return } var resB bytes.Buffer _, err = resB.ReadFrom(r) if err != nil { return } resData = resB.Bytes() return } func UpdateResponse(r *http.Response) error { contentType := r.Header[http.CanonicalHeaderKey("content-type")] contentEncoding := r.Header[http.CanonicalHeaderKey("content-encoding")] location := r.Header[http.CanonicalHeaderKey("location")] statusCode := r.StatusCode log.WithFields( log.Fields{ "r.Header": r.Header, "statusCode": statusCode, "contentType": contentType, "contentEncoding": contentEncoding, "location": location, }, ).Debug() if statusCode == http.StatusFound && strings.HasPrefix(proxyURL, "http://pastebin") && len(contentType) == 0 { if len(location) > 0 { r.Header.Del("location") r.Header.Set("location", fmt.Sprintf("/pastebin%s", location[0])) } } if statusCode != http.StatusOK { log.Debug("skipping not status ok reponse") return nil } if len(contentType) > 0 && strings.HasPrefix(contentType[0], "text/html") { var ( body []byte err error ) if body, err = io.ReadAll(r.Body); err != nil { fmt.Println(err) return err } if len(contentEncoding) > 0 && strings.HasPrefix(contentEncoding[0], "gzip") { if body, err = gUnzipData(body); err != nil { fmt.Println(err) return err } } stringBody := string(body) if strings.HasPrefix(proxyURL, "http://pastebin") { updatedStringbody = strings.Replace(stringBody, "action=\"/\"", "action=\"/pastebin/\"", 1) } else if strings.HasPrefix(proxyURL, "http://cinny") { updatedStringbody = strings.Replace(stringBody, ``, ``+updatedMenu, 1) } else { updatedStringbody = strings.Replace(stringBody, "", ""+updatedMenu, 1) } buf := bytes.NewBufferString(updatedStringbody) r.Body = ioutil.NopCloser(buf) r.Header.Del("content-encoding") r.Header.Del("content-type") r.Header.Set("content-type", "text/html; charset=utf-8") r.Header.Set("content-length", fmt.Sprint(buf.Len())) } return nil } func init() { flag.StringVar(&proxyURL, "proxyurl", "", "proxy URL") flag.StringVar(&codefirstURL, "codefirsturl", "", "codefirst URL") flag.BoolVar(&debug, "debug", false, "enable debug") flag.BoolVar(&dump, "dump", false, "dump menu") flag.Parse() updatedMenu = menu.CodeFirstMenu if dump { updatedMenu = strings.Replace(updatedMenu, "", "", 1) fmt.Println(updatedMenu) os.Exit(0) } if proxyURL == "" { panic(errors.New("empty proxy URL")) } if debug { log.SetLevel(log.DebugLevel) } updatedMenu = strings.ReplaceAll(updatedMenu, "CODEFIRST_HOSTNAME", codefirstURL) if strings.HasPrefix(proxyURL, "http://gitea") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://drone") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://dockerrunner") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://registryui") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://sonarqube") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://nginx") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } else if strings.HasPrefix(proxyURL, "http://cinny") { updatedMenu = strings.Replace(updatedMenu, "", "", 1) } } func main() { remote, err := url.Parse(proxyURL) if err != nil { panic(err) } log.WithFields( log.Fields{ "proxyURL": proxyURL, "updatedMenu": updatedMenu, }, ).Debug() handler := func(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { log.WithFields( log.Fields{ "r.Host": r.Host, "r.RequestURI": r.RequestURI, }, ).Debug() r.Host = remote.Host p.ServeHTTP(w, r) } } proxy := httputil.NewSingleHostReverseProxy(remote) proxy.ModifyResponse = UpdateResponse http.HandleFunc("/", handler(proxy)) err = http.ListenAndServe(":8081", nil) if err != nil { panic(err) } }