feat: add supervisor prototype with embedded frontend
This commit is contained in:
131
internal/httpserver/handlers/sessions.go
Normal file
131
internal/httpserver/handlers/sessions.go
Normal file
@ -0,0 +1,131 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"supervisor/internal/domain"
|
||||
"supervisor/internal/session"
|
||||
)
|
||||
|
||||
type SessionService interface {
|
||||
CreateSession(ctx context.Context, params session.CreateSessionParams) (domain.Session, error)
|
||||
StartSession(ctx context.Context, id string) error
|
||||
StopSession(ctx context.Context, id string) error
|
||||
DeleteSession(ctx context.Context, id string) error
|
||||
ListSessions(ctx context.Context) ([]domain.Session, error)
|
||||
GetSession(ctx context.Context, id string) (domain.Session, error)
|
||||
WriteInput(ctx context.Context, id string, input string) error
|
||||
Resize(ctx context.Context, id string, cols, rows int) error
|
||||
Subscribe(id string) (<-chan domain.Event, func(), error)
|
||||
Scrollback(id string) ([]byte, error)
|
||||
}
|
||||
|
||||
type SessionsHandler struct {
|
||||
manager SessionService
|
||||
}
|
||||
|
||||
func NewSessionsHandler(manager SessionService) *SessionsHandler {
|
||||
return &SessionsHandler{manager: manager}
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
sessions, err := h.manager.ListSessions(r.Context())
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, sessions)
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
var req session.CreateSessionParams
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
created, err := h.manager.CreateSession(r.Context(), req)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if err := h.manager.StartSession(r.Context(), created.ID); err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
current, err := h.manager.GetSession(r.Context(), created.ID)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusCreated, current)
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
item, err := h.manager.GetSession(r.Context(), id)
|
||||
if err != nil {
|
||||
if errors.Is(err, session.ErrSessionNotFound) {
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, item)
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) Input(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
var req session.InputRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if err := h.manager.WriteInput(r.Context(), id, req.Input); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]bool{"ok": true})
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) Stop(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
if err := h.manager.StopSession(r.Context(), id); err != nil {
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
item, err := h.manager.GetSession(r.Context(), id)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, item)
|
||||
}
|
||||
|
||||
func (h *SessionsHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
if err := h.manager.DeleteSession(r.Context(), id); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, session.ErrSessionNotFound):
|
||||
writeError(w, http.StatusNotFound, err)
|
||||
case errors.Is(err, session.ErrSessionRunning):
|
||||
writeError(w, http.StatusConflict, err)
|
||||
default:
|
||||
writeError(w, http.StatusBadRequest, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, code int, payload any) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(code)
|
||||
_ = json.NewEncoder(w).Encode(payload)
|
||||
}
|
||||
|
||||
func writeError(w http.ResponseWriter, code int, err error) {
|
||||
writeJSON(w, code, map[string]string{"error": err.Error()})
|
||||
}
|
||||
Reference in New Issue
Block a user