package app import ( "net" "net/http" "forge.cadoles.com/arcad/edge/pkg/app" "github.com/go-chi/chi/v5" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/api" "gitlab.com/wpetit/goweb/logger" ) type MountFunc func(r chi.Router) type Handler struct { repo Repository } func (h *Handler) serveApps(w http.ResponseWriter, r *http.Request) { manifests, err := h.repo.List(r.Context()) if err != nil { logger.Error(r.Context(), "could not retrieve app manifest", logger.CapturedE(errors.WithStack(err))) api.ErrorResponse(w, http.StatusInternalServerError, api.ErrCodeUnknownError, nil) return } api.DataResponse(w, http.StatusOK, struct { Manifests []*app.Manifest `json:"manifests"` }{ Manifests: manifests, }) } func (h *Handler) serveApp(w http.ResponseWriter, r *http.Request) { appID := app.ID(chi.URLParam(r, "appID")) manifest, err := h.repo.Get(r.Context(), appID) if err != nil { if errors.Is(err, ErrNotFound) { api.ErrorResponse(w, http.StatusNotFound, api.ErrCodeNotFound, nil) return } logger.Error(r.Context(), "could not retrieve app manifest", logger.CapturedE(errors.WithStack(err))) api.ErrorResponse(w, http.StatusInternalServerError, api.ErrCodeUnknownError, nil) return } api.DataResponse(w, http.StatusOK, struct { Manifest *app.Manifest `json:"manifest"` }{ Manifest: manifest, }) } type serveAppURLRequest struct { From string `json:"from,omitempty"` } func (h *Handler) serveAppURL(w http.ResponseWriter, r *http.Request) { ctx := r.Context() req := &serveAppURLRequest{} if ok := api.Bind(w, r, req); !ok { return } appID := app.ID(chi.URLParam(r, "appID")) from := req.From if from == "" { from = retrieveRemoteAddr(r) } url, err := h.repo.GetURL(ctx, appID, from) if err != nil { if errors.Is(err, ErrNotFound) { api.ErrorResponse(w, http.StatusNotFound, api.ErrCodeNotFound, nil) return } logger.Error(r.Context(), "could not retrieve app url", logger.CapturedE(errors.WithStack(err))) api.ErrorResponse(w, http.StatusInternalServerError, api.ErrCodeUnknownError, nil) return } api.DataResponse(w, http.StatusOK, struct { URL string `json:"url"` }{ URL: url, }) } func Mount(repository Repository) MountFunc { handler := &Handler{repository} return func(r chi.Router) { r.Get("/api/v1/apps", handler.serveApps) r.Get("/api/v1/apps/{appID}", handler.serveApp) r.Post("/api/v1/apps/{appID}/url", handler.serveAppURL) } } func retrieveRemoteAddr(r *http.Request) string { host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { host = r.RemoteAddr } return host }