feat: status api

This commit is contained in:
Ilia Denisov
2026-01-07 18:38:06 +02:00
parent 1b0ab7a079
commit 204d3df8cf
20 changed files with 188 additions and 40 deletions
+3 -7
View File
@@ -7,7 +7,6 @@ import (
"github.com/iliadenisov/galaxy/internal/game"
"github.com/gin-gonic/gin"
"github.com/iliadenisov/galaxy/internal/controller"
"github.com/iliadenisov/galaxy/internal/model/rest"
)
@@ -26,18 +25,15 @@ func CommandHandler(c *gin.Context, executor Executor) {
case err == nil:
c.Status(http.StatusOK)
case errors.Is(err, ErrCommandNotProcessed):
c.Status(http.StatusInternalServerError)
c.Status(http.StatusInternalServerError) // TODO: add error text?
default:
// TODO: separate bad value errors and game state errors
// TODO: separate invalid input and game state errors
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
}
func Execute(cmd rest.Command) error {
p := func(p *controller.Param) {
// TODO: initialize base controller settings
p.StoragePath = ""
}
p := param()
switch {
case cmd.DeclareWar != nil:
return game.DeclareWar(p, cmd.Race, cmd.DeclareWar.Opponent)
+19
View File
@@ -1,12 +1,30 @@
package router
import (
"os"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"github.com/iliadenisov/galaxy/internal/controller"
"github.com/iliadenisov/galaxy/internal/model/rest"
)
var (
StoragePath string
)
func init() {
StoragePath = os.Getenv("STORAGE_PATH")
}
func param() func(*controller.Param) {
return func(p *controller.Param) {
// TODO: initialize base controller settings
p.StoragePath = StoragePath
}
}
type Executor func(rest.Command) error
type Router struct {
@@ -35,6 +53,7 @@ func setupRouter(executor Executor) *gin.Engine {
v.RegisterValidation("notblank", notBlankStringValidator)
}
r.GET("/api/v1/status", StatusHandler)
r.PUT("/api/v1/command", LimitMiddleware(1), func(ctx *gin.Context) { CommandHandler(ctx, executor) })
return r
}
+1 -1
View File
@@ -29,7 +29,7 @@ func TestRouter(t *testing.T) {
req, _ := http.NewRequest("PUT", "/api/v1/command", cmdBody(exampleCommand))
r.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code, w.Body)
assert.Equal(t, http.StatusOK, w.Code, w.Body)
// error: notblank validator
exampleCommand.Race = ""
+37
View File
@@ -0,0 +1,37 @@
package router
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
e "github.com/iliadenisov/galaxy/internal/error"
"github.com/iliadenisov/galaxy/internal/game"
"github.com/iliadenisov/galaxy/internal/model/rest"
)
func StatusHandler(c *gin.Context) {
g, err := game.LoadState(param())
if err == nil {
c.JSON(http.StatusOK, rest.Status{
Turn: g.Age,
Players: len(g.Race),
})
return
}
var ge = new(e.GenericError)
if errors.As(err, ge) {
switch ge.Code {
case e.ErrGameNotInitialized:
c.Status(http.StatusNotImplemented)
default:
c.JSON(http.StatusInternalServerError, gin.H{"generic_error": ge.Error(), "code": ge.Code})
}
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
}
+21
View File
@@ -0,0 +1,21 @@
package router_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/iliadenisov/galaxy/internal/router"
"github.com/stretchr/testify/assert"
)
func TestGetStatus(t *testing.T) {
r := router.SetupRouter()
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/api/v1/status", nil)
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusNotImplemented, w.Code, w.Body)
}