package common import ( "log" "net/http" "net/url" ) const RequestType_Push = "push" const RequestType_Repository = "repository" const RequestType_PR = "pull_request" const RequestType_PR_sync = "pull_request_sync" type RequestProcessor func(*RequestHandler) error type ListenDefinitions struct { GitAuthor, Url string Handlers map[string]RequestProcessor } func StartServer(listenDefs ListenDefinitions) { StartServerWithAddress(listenDefs, "[::1]:8000") } func StartServerWithAddress(listenDefs ListenDefinitions, addr string) { if listenDefs.Url != url.PathEscape(listenDefs.Url) { log.Fatalf("Invalid Url fragment (%s) to listen on. Aborting", listenDefs.Url) } http.HandleFunc("/"+listenDefs.Url, func(res http.ResponseWriter, req *http.Request) { h := CreateRequestHandler(listenDefs.GitAuthor, listenDefs.Url) defer h.Close() if len(req.Header.Get("Content-Type")) == 0 || req.Header["Content-Type"][0] != "application/json" || req.Method != "POST" { h.WriteError() res.WriteHeader(http.StatusInternalServerError) return } hdr := req.Header[GiteaRequestHeader] if len(hdr) != 1 { h.ErrLogger.Printf("Unsupported number of %s headers: %d: %#v\n", GiteaRequestHeader, len(hdr), hdr) h.WriteError() res.WriteHeader(http.StatusInternalServerError) return } reqType := hdr[0] if handler, ok := listenDefs.Handlers[reqType]; ok { switch reqType { case RequestType_Repository: h.parseRepositoryRequest(req.Body) case RequestType_Push: h.parsePushRequest(req.Body) case RequestType_PR: h.parsePullRequest(req.Body) case RequestType_PR_sync: h.parsePullRequestSync(req.Body) default: h.ErrLogger.Printf("Unhandled request type: %s\n", reqType) res.WriteHeader(http.StatusInternalServerError) return } if h.HasError() { h.ErrLogger.Printf("error in parser %s: %v\n", reqType, h.Error) res.WriteHeader(http.StatusInternalServerError) return } if err := handler(h); err != nil { h.ErrLogger.Printf("error in handler for %s: %v\n", reqType, err) res.WriteHeader(http.StatusInternalServerError) return } } else { h.ErrLogger.Printf("Unsupported request type: %s\n", reqType) res.WriteHeader(http.StatusInternalServerError) return } if h.HasError() { h.WriteError() res.WriteHeader(http.StatusInternalServerError) return } res.Header().Add("Content-Type", "application/json") res.WriteHeader(http.StatusOK) }) log.Fatal(http.ListenAndServe(addr, nil)) }