149 lines
3.8 KiB
Go
149 lines
3.8 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
"mirror-sync/cmd/server/core/storage"
|
|
"mirror-sync/pkg/constants"
|
|
"mirror-sync/pkg/project"
|
|
"mirror-sync/pkg/remote/obj"
|
|
"net/http"
|
|
"runtime"
|
|
|
|
cronruntime "mirror-sync/cmd/server/core/runtime"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
)
|
|
|
|
type (
|
|
HTTPServer struct {
|
|
Server *http.Server
|
|
data *storage.Repository
|
|
scheduler *cronruntime.Scheduler
|
|
}
|
|
)
|
|
|
|
func NewServer(data *storage.Repository, scheduler *cronruntime.Scheduler, addr string, port int) *HTTPServer {
|
|
s := &HTTPServer{
|
|
data: data,
|
|
scheduler: scheduler,
|
|
}
|
|
router := chi.NewRouter()
|
|
router.NotFound(func(writer http.ResponseWriter, request *http.Request) {
|
|
notFound("id not found", writer, request)
|
|
})
|
|
router.MethodNotAllowed(func(writer http.ResponseWriter, request *http.Request) {
|
|
methodNotAllowed(writer, request)
|
|
})
|
|
chi.RegisterMethod("EXECUTE")
|
|
router.Use(middleware.Logger)
|
|
router.Use(recoverMiddleware)
|
|
router.Use(middleware.GetHead)
|
|
router.Use(middleware.Compress(5, "application/gzip"))
|
|
router.Use(middleware.Heartbeat("/heartbeat"))
|
|
router.Route("/api", func(routerAPI chi.Router) {
|
|
routerAPI.Route("/v1", func(r chi.Router) {
|
|
// Get information about the server
|
|
r.Get("/version", s.Information)
|
|
r.MethodFunc("EXECUTE", "/run", s.RunProjectHandler)
|
|
r.Route("/projects", func(r chi.Router) {
|
|
r.Get("/all", s.ProjectsGetHandler)
|
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {})
|
|
r.Post("/", s.ProjectPostHandler)
|
|
r.Delete("/", s.ProjectDeleteHandler)
|
|
})
|
|
})
|
|
})
|
|
s.Server = &http.Server{
|
|
Addr: fmt.Sprintf("%s:%d", addr, port),
|
|
Handler: router,
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *HTTPServer) Information(w http.ResponseWriter, r *http.Request) {
|
|
info := obj.SystemInformation{
|
|
Version: constants.Version,
|
|
APIVersion: constants.ApiVersion,
|
|
GoVersion: runtime.Version(),
|
|
OSName: runtime.GOOS,
|
|
OSArchitecture: runtime.GOARCH,
|
|
}
|
|
ok(info, w, r)
|
|
}
|
|
|
|
func (s *HTTPServer) ProjectPostHandler(w http.ResponseWriter, r *http.Request) {
|
|
var pr project.Project
|
|
d := json.NewDecoder(r.Body)
|
|
if err := d.Decode(&pr); err != nil {
|
|
slog.Error("failed to parse project description", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
if err := s.data.Save(pr); err != nil {
|
|
slog.Error("failed to save project to the database", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
s.scheduler.Remove(pr)
|
|
if err := s.scheduler.Add(pr); err != nil {
|
|
slog.Error("failed to run project", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(201)
|
|
}
|
|
|
|
func (s *HTTPServer) ProjectDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|
var pr project.Project
|
|
d := json.NewDecoder(r.Body)
|
|
if err := d.Decode(&pr); err != nil {
|
|
slog.Error("failed to parse project description", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
s.scheduler.Remove(pr)
|
|
if err := s.data.Remove(pr); err != nil {
|
|
slog.Error("failed to remove project", "err", err, "uuid", pr.UUID)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(204)
|
|
}
|
|
|
|
func (s *HTTPServer) ProjectsGetHandler(w http.ResponseWriter, r *http.Request) {
|
|
prs, err := s.data.List()
|
|
if err != nil {
|
|
slog.Error("failed to fetch all the projects from the database", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
ok(prs, w, r)
|
|
}
|
|
|
|
func (s *HTTPServer) RunProjectHandler(w http.ResponseWriter, r *http.Request) {
|
|
var pr project.Project
|
|
d := json.NewDecoder(r.Body)
|
|
if err := d.Decode(&pr); err != nil {
|
|
slog.Error("failed to parse project description", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
if err := s.scheduler.RunOnce(pr); err != nil {
|
|
slog.Error("failed to run the project", "err", err)
|
|
internalServerError(err, w, r)
|
|
return
|
|
}
|
|
|
|
ok("ok", w, r)
|
|
}
|