package main import ( "bytes" "encoding/json" "flag" "fmt" "io" "net/http" "time" "src.opensuse.org/autogits/common" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) type Status struct { Context string `json:"context"` Description string `json:"description"` State string `json:"state"` TargetUrl string `json:"target_url"` } func main() { configFile := flag.String("config", "", "status proxy config file") flag.Parse() if *configFile == "" { common.LogError("missing required argument config") return } config, err := ReadConfigFile(*configFile) if err != nil { common.LogError("Failed to read config file", err) return } r := chi.NewRouter() r.Use(ConfigMiddleWare(config)) r.Use(middleware.RequestID) r.Use(middleware.RealIP) r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) r.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hi")) }) r.Route("/repos/{owner}/{repo}/statuses/{sha}", func(r chi.Router) { r.Use(ProxyAuthMiddleware) r.Post("/", StatusProxy) }) common.LogInfo("server up and listening on :3000") err = http.ListenAndServe(":3000", r) if err != nil { common.LogError("Server failed to start up", err) } } func StatusProxy(w http.ResponseWriter, r *http.Request) { owner := chi.URLParam(r, "owner") repo := chi.URLParam(r, "repo") sha := chi.URLParam(r, "sha") config, ok := r.Context().Value(configKey).(*Config) if !ok { common.LogError("Failed to get config from context, is it set?") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } posturl := fmt.Sprintf("%s/repos/%s/%s/statuses/%s", config.ForgeEndpoint, owner, repo, sha) decoder := json.NewDecoder(r.Body) var status Status err := decoder.Decode(&status) if err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } status_payload, err := json.Marshal(status) if err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } client := &http.Client{} req, err := http.NewRequest("POST", posturl, bytes.NewBuffer(status_payload)) if err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } req.Header.Add("Content-Type", "Content-Type") req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.ForgeToken)) resp, err := client.Do(req) if err != nil { common.LogError(fmt.Sprintf("Request to forge endpoint failed: %v", err)) http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) return } defer resp.Body.Close() w.Header().Set("Content-Type", "application/json") w.WriteHeader(resp.StatusCode) /* the commented out section sets every key value from the headers, unsure if this leaks information from gitea for k, v := range resp.Header { for _, vv := range v { w.Header().Add(k, vv) } } */ _, err = io.Copy(w, resp.Body) if err != nil { common.LogError("Error copying response body: %v", err) } }