feat: api - add a new endpoint - GET /api/v2/versions/{versionCode}/servers/{serverKey}
This commit is contained in:
parent
79337cd60a
commit
6d61e43143
|
@ -67,6 +67,21 @@ paths:
|
||||||
$ref: "#/components/responses/ListServersResponse"
|
$ref: "#/components/responses/ListServersResponse"
|
||||||
default:
|
default:
|
||||||
$ref: "#/components/responses/ErrorResponse"
|
$ref: "#/components/responses/ErrorResponse"
|
||||||
|
/v2/versions/{versionCode}/servers/{serverKey}:
|
||||||
|
get:
|
||||||
|
operationId: getServer
|
||||||
|
tags:
|
||||||
|
- versions
|
||||||
|
- servers
|
||||||
|
description: Get a server
|
||||||
|
parameters:
|
||||||
|
- $ref: "#/components/parameters/VersionCodePathParam"
|
||||||
|
- $ref: "#/components/parameters/ServerKeyPathParam"
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
$ref: "#/components/responses/GetServerResponse"
|
||||||
|
default:
|
||||||
|
$ref: "#/components/responses/ErrorResponse"
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Error:
|
Error:
|
||||||
|
@ -205,6 +220,12 @@ components:
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
ServerKeyPathParam:
|
||||||
|
in: path
|
||||||
|
name: serverKey
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
responses:
|
responses:
|
||||||
ListVersionsResponse:
|
ListVersionsResponse:
|
||||||
description: ""
|
description: ""
|
||||||
|
@ -247,6 +268,17 @@ components:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/Server"
|
$ref: "#/components/schemas/Server"
|
||||||
|
GetServerResponse:
|
||||||
|
description: ""
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- data
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
$ref: "#/components/schemas/Server"
|
||||||
ErrorResponse:
|
ErrorResponse:
|
||||||
description: Default error response.
|
description: Default error response.
|
||||||
content:
|
content:
|
||||||
|
|
|
@ -307,3 +307,36 @@ func (svc *ServerService) UpdatePlayerSnapshotsCreatedAt(
|
||||||
|
|
||||||
return svc.repo.Update(ctx, key, updateParams)
|
return svc.repo.Update(ctx, key, updateParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *ServerService) GetNormalByVersionCodeAndServerKey(
|
||||||
|
ctx context.Context,
|
||||||
|
versionCode, key string,
|
||||||
|
) (domain.Server, error) {
|
||||||
|
params := domain.NewListServersParams()
|
||||||
|
if err := params.SetVersionCodes([]string{versionCode}); err != nil {
|
||||||
|
return domain.Server{}, err
|
||||||
|
}
|
||||||
|
if err := params.SetKeys([]string{key}); err != nil {
|
||||||
|
return domain.Server{}, err
|
||||||
|
}
|
||||||
|
if err := params.SetSpecial(domain.NullBool{
|
||||||
|
Value: false,
|
||||||
|
Valid: true,
|
||||||
|
}); err != nil {
|
||||||
|
return domain.Server{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := svc.repo.List(ctx, params)
|
||||||
|
if err != nil {
|
||||||
|
return domain.Server{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
servers := res.Servers()
|
||||||
|
if len(servers) == 0 {
|
||||||
|
return domain.Server{}, domain.ServerNotFoundError{
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers[0], nil
|
||||||
|
}
|
||||||
|
|
|
@ -62,8 +62,12 @@ func NewAPIHTTPHandler(
|
||||||
r.MethodNotAllowed(h.handleMethodNotAllowed)
|
r.MethodNotAllowed(h.handleMethodNotAllowed)
|
||||||
|
|
||||||
return apimodel.HandlerWithOptions(h, apimodel.ChiServerOptions{
|
return apimodel.HandlerWithOptions(h, apimodel.ChiServerOptions{
|
||||||
BaseRouter: r,
|
BaseRouter: r,
|
||||||
Middlewares: []apimodel.MiddlewareFunc{middleware.NoCache},
|
Middlewares: []apimodel.MiddlewareFunc{
|
||||||
|
middleware.NoCache,
|
||||||
|
h.versionMiddleware,
|
||||||
|
h.serverMiddleware,
|
||||||
|
},
|
||||||
ErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
|
ErrorHandlerFunc: func(w http.ResponseWriter, r *http.Request, err error) {
|
||||||
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package port
|
package port
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *apiHTTPHandler) ListServers(
|
func (h *apiHTTPHandler) ListServers(
|
||||||
|
@ -58,6 +61,53 @@ func (h *apiHTTPHandler) ListServers(
|
||||||
renderJSON(w, r, http.StatusOK, apimodel.NewListServersResponse(res))
|
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) 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 {
|
||||||
|
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
||||||
|
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 formatListServersParamsErrorPath(segments []errorPathSegment) []string {
|
func formatListServersParamsErrorPath(segments []errorPathSegment) []string {
|
||||||
if segments[0].model != "ListServersParams" {
|
if segments[0].model != "ListServersParams" {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package port
|
package port
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/port/internal/apimodel"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *apiHTTPHandler) ListVersions(w http.ResponseWriter, r *http.Request, params apimodel.ListVersionsParams) {
|
func (h *apiHTTPHandler) ListVersions(w http.ResponseWriter, r *http.Request, params apimodel.ListVersionsParams) {
|
||||||
|
@ -33,16 +36,43 @@ func (h *apiHTTPHandler) ListVersions(w http.ResponseWriter, r *http.Request, pa
|
||||||
renderJSON(w, r, http.StatusOK, apimodel.NewListVersionsResponse(res))
|
renderJSON(w, r, http.StatusOK, apimodel.NewListVersionsResponse(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *apiHTTPHandler) GetVersion(w http.ResponseWriter, r *http.Request, versionCode apimodel.VersionCodePathParam) {
|
func (h *apiHTTPHandler) GetVersion(w http.ResponseWriter, r *http.Request, _ apimodel.VersionCodePathParam) {
|
||||||
version, err := h.versionSvc.Get(r.Context(), versionCode)
|
version, _ := versionFromContext(r.Context())
|
||||||
if err != nil {
|
|
||||||
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
renderJSON(w, r, http.StatusOK, apimodel.NewGetVersionResponse(version))
|
renderJSON(w, r, http.StatusOK, apimodel.NewGetVersionResponse(version))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *apiHTTPHandler) versionMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
routeCtx := chi.RouteContext(ctx)
|
||||||
|
idx := slices.Index(routeCtx.URLParams.Keys, "versionCode")
|
||||||
|
|
||||||
|
if idx < 0 {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := h.versionSvc.Get(ctx, routeCtx.URLParams.Values[idx])
|
||||||
|
if err != nil {
|
||||||
|
apiErrorRenderer{errors: []error{err}}.render(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(w, r.WithContext(versionToContext(ctx, version)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type versionCtxKey struct{}
|
||||||
|
|
||||||
|
func versionToContext(ctx context.Context, v domain.Version) context.Context {
|
||||||
|
return context.WithValue(ctx, versionCtxKey{}, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func versionFromContext(ctx context.Context) (domain.Version, bool) {
|
||||||
|
v, ok := ctx.Value(versionCtxKey{}).(domain.Version)
|
||||||
|
return v, ok
|
||||||
|
}
|
||||||
|
|
||||||
func formatListVersionsParamsErrorPath(segments []errorPathSegment) []string {
|
func formatListVersionsParamsErrorPath(segments []errorPathSegment) []string {
|
||||||
if segments[0].model != "ListVersionsParams" {
|
if segments[0].model != "ListVersionsParams" {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package apimodel
|
||||||
|
|
||||||
|
//go:generate oapi-codegen --config=config.yml ../../../../api/openapi3.yml
|
|
@ -54,3 +54,9 @@ func NewListServersResponse(res domain.ListServersResult) ListServersResponse {
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewGetServerResponse(v domain.Server) GetServerResponse {
|
||||||
|
return GetServerResponse{
|
||||||
|
Data: NewServer(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package apimodel
|
||||||
|
|
||||||
import "gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
import "gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
|
|
||||||
//go:generate oapi-codegen --config=config.yml ../../../../api/openapi3.yml
|
|
||||||
|
|
||||||
func NewVersion(v domain.Version) Version {
|
func NewVersion(v domain.Version) Version {
|
||||||
return Version{
|
return Version{
|
||||||
Code: v.Code(),
|
Code: v.Code(),
|
||||||
|
|
Loading…
Reference in New Issue