core/internal/port/handler_http_api_server.go

170 lines
4.3 KiB
Go

package port
import (
"context"
"net/http"
"slices"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
"github.com/go-chi/chi/v5"
)
func (h *apiHTTPHandler) ListServers(
w http.ResponseWriter,
r *http.Request,
versionCode apimodel.VersionCodePathParam,
params apimodel.ListServersParams,
) {
domainParams := domain.NewListServersParams()
if err := domainParams.SetSort([]domain.ServerSort{domain.ServerSortOpenDESC, domain.ServerSortKeyASC}); err != nil {
h.errorRenderer.withErrorPathFormatter(formatListServersErrorPath).render(w, r, err)
return
}
if err := domainParams.SetVersionCodes([]string{versionCode}); err != nil {
h.errorRenderer.withErrorPathFormatter(formatListServersErrorPath).render(w, r, err)
return
}
if params.Open != nil {
if err := domainParams.SetOpen(domain.NullBool{
V: *params.Open,
Valid: true,
}); err != nil {
h.errorRenderer.withErrorPathFormatter(formatListServersErrorPath).render(w, r, err)
return
}
}
if params.Limit != nil {
if err := domainParams.SetLimit(*params.Limit); err != nil {
h.errorRenderer.withErrorPathFormatter(formatListServersErrorPath).render(w, r, err)
return
}
}
if params.Cursor != nil {
if err := domainParams.SetEncodedCursor(*params.Cursor); err != nil {
h.errorRenderer.withErrorPathFormatter(formatListServersErrorPath).render(w, r, err)
return
}
}
res, err := h.serverSvc.List(r.Context(), domainParams)
if err != nil {
h.errorRenderer.render(w, r, err)
return
}
renderJSON(w, r, http.StatusOK, apimodel.NewListServersResponse(res))
}
func (h *apiHTTPHandler) GetServer(
w http.ResponseWriter,
r *http.Request,
_ apimodel.VersionCodePathParam,
_ apimodel.ServerKeyPathParam,
) {
server, _ := serverFromContext(r.Context())
renderJSON(w, r, http.StatusOK, apimodel.NewGetServerResponse(server))
}
func (h *apiHTTPHandler) GetBuildingInfo(
w http.ResponseWriter,
r *http.Request,
_ apimodel.VersionCodePathParam,
_ apimodel.ServerKeyPathParam,
) {
server, _ := serverFromContext(r.Context())
renderJSON(w, r, http.StatusOK, apimodel.NewGetBuildingInfoResponse(server.BuildingInfo()))
}
func (h *apiHTTPHandler) GetServerConfig(
w http.ResponseWriter,
r *http.Request,
_ apimodel.VersionCodePathParam,
_ apimodel.ServerKeyPathParam,
) {
server, _ := serverFromContext(r.Context())
renderJSON(w, r, http.StatusOK, apimodel.NewGetServerConfigResponse(server.Config()))
}
func (h *apiHTTPHandler) GetUnitInfo(
w http.ResponseWriter,
r *http.Request,
_ apimodel.VersionCodePathParam,
_ apimodel.ServerKeyPathParam,
) {
server, _ := serverFromContext(r.Context())
renderJSON(w, r, http.StatusOK, apimodel.NewGetUnitInfoResponse(server.UnitInfo()))
}
func (h *apiHTTPHandler) serverMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
routeCtx := chi.RouteContext(ctx)
version, versionOK := versionFromContext(ctx)
serverKeyIdx := slices.Index(routeCtx.URLParams.Keys, "serverKey")
if !versionOK || serverKeyIdx < 0 {
next.ServeHTTP(w, r)
return
}
server, err := h.serverSvc.GetNormalByVersionCodeAndServerKey(
ctx,
version.Code(),
routeCtx.URLParams.Values[serverKeyIdx],
)
if err != nil {
h.errorRenderer.withErrorPathFormatter(formatGetServerErrorPath).render(w, r, err)
return
}
next.ServeHTTP(w, r.WithContext(serverToContext(ctx, server)))
})
}
type serverCtxKey struct{}
func serverToContext(ctx context.Context, s domain.Server) context.Context {
return context.WithValue(ctx, serverCtxKey{}, s)
}
func serverFromContext(ctx context.Context) (domain.Server, bool) {
s, ok := ctx.Value(serverCtxKey{}).(domain.Server)
return s, ok
}
func formatListServersErrorPath(segments []domain.ErrorPathSegment) []string {
if segments[0].Model != "ListServersParams" {
return nil
}
switch segments[0].Field {
case "cursor":
return []string{"$query", "cursor"}
case "limit":
return []string{"$query", "limit"}
case "open":
return []string{"$query", "open"}
default:
return nil
}
}
func formatGetServerErrorPath(segments []domain.ErrorPathSegment) []string {
if segments[0].Model != "ListServersParams" {
return nil
}
switch segments[0].Field {
case "keys":
return []string{"$path", "serverKey"}
default:
return nil
}
}