package main import ( "encoding/json" "fmt" "log" "net/http" "net/http/httputil" "os" "strings" ) type listeners struct { Maven string `json:"maven"` Cargo string `json:"cargo"` } type config struct { Listen listeners `json:"listen"` Domain string `json:"domain"` Organizations []string `json:"organizations"` } func searcher(config *config, dst string, useGet bool, w http.ResponseWriter, r *http.Request) { for _, org := range config.Organizations { actualUrl := fmt.Sprintf( dst, config.Domain, org, strings.TrimLeft(r.URL.Path, "/"), ) var resp *http.Response var err error if useGet { resp, err = http.Get(actualUrl) } else { resp, err = http.Head(actualUrl) } if err != nil { w.WriteHeader(500) _, err := fmt.Fprintf(w, "%v", err) if err != nil { log.Fatal(err) } return } switch resp.StatusCode { case 200: w.Header().Set("Location", actualUrl) w.WriteHeader(307) return case 404: fallthrough case 403: continue case 502: fallthrough case 503: w.WriteHeader(503) return default: w.WriteHeader(500) rawResp, err := httputil.DumpResponse(resp, true) if err != nil { log.Fatal(err) return } _, err = w.Write(rawResp) if err != nil { log.Fatal(err) return } return } } w.WriteHeader(404) } func readConfig(path string) config { file, err := os.Open(path) if err != nil { panic(err) } var data config if err := json.NewDecoder(file).Decode(&data); err != nil { panic(err) } if err := file.Close(); err != nil { panic(err) } return data } func main() { if len(os.Args) < 2 { fmt.Println("Missed path to config") return } if len(os.Args) > 2 { fmt.Println("Excess arguments") return } config := readConfig(os.Args[1]) if config.Organizations == nil { fmt.Println("Missed organizations list") return } go func() { dispatcher := http.NewServeMux() dispatcher.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { searcher(&config, "https://%s/api/packages/%s/maven/%s", false, w, r) }) server := http.Server{ Addr: config.Listen.Maven, Handler: dispatcher, } log.Fatal(server.ListenAndServe()) }() go func() { dispatcher := http.NewServeMux() dispatcher.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { searcher(&config, "https://%s/api/packages/%s/cargo/%s", true, w, r) }) server := http.Server{ Addr: config.Listen.Cargo, Handler: dispatcher, } log.Fatal(server.ListenAndServe()) }() select {} }