autogits/bots-common/listen.go
2024-08-24 13:32:39 +02:00

96 lines
2.5 KiB
Go

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))
}