init: first steps

This commit is contained in:
2025-07-20 23:50:47 +03:00
commit 5f26ad6941
25 changed files with 1134 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
package controller
import (
"github.com/go-andiamo/chioas"
"github.com/go-chi/chi/v5"
)
type Controller interface {
New() Controller
Group(r chi.Router)
Documentate() (*chioas.Paths, *chioas.Components)
}

View File

@@ -0,0 +1,57 @@
package ping
import (
"net/http"
"git.ostiwe.com/ostiwe-com/status/modules/log"
"git.ostiwe.com/ostiwe-com/status/router/controller"
"github.com/go-andiamo/chioas"
"github.com/go-chi/chi/v5"
)
type Controller struct {
}
func (Controller) New() controller.Controller {
return &Controller{}
}
func (c *Controller) Group(r chi.Router) {
r.Get("/ping", c.PingHandler)
}
func (c *Controller) PingHandler(w http.ResponseWriter, _ *http.Request) {
_, err := w.Write([]byte("pong"))
if err != nil {
log.Global.Get(log.SERVER).Error(err)
return
}
}
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
return &chioas.Paths{
"/ping": chioas.Path{
Methods: map[string]chioas.Method{
http.MethodGet: {
Handler: c.PingHandler,
Responses: chioas.Responses{
http.StatusOK: {
ContentType: "plain/text",
Schema: chioas.Schema{Type: "string"},
Examples: chioas.Examples{
{
Name: "200 OK",
Value: "pong",
},
},
},
},
},
},
Tag: "service",
Comment: "Route for check service is alive",
},
}, nil
}

View File

@@ -0,0 +1,106 @@
package service
import (
"net/http"
"git.ostiwe.com/ostiwe-com/status/modules/log"
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
"git.ostiwe.com/ostiwe-com/status/repository"
"git.ostiwe.com/ostiwe-com/status/router/controller"
"git.ostiwe.com/ostiwe-com/status/transform"
"github.com/go-andiamo/chioas"
"github.com/go-chi/chi/v5"
)
type Controller struct {
serviceRepository repository.Service
}
func (c Controller) New() controller.Controller {
return &Controller{
serviceRepository: repository.NewServiceRepository(),
}
}
func (c *Controller) Group(r chi.Router) {
c.public(r)
c.internal(r)
}
func (c *Controller) public(r chi.Router) {
r.Get("/api/public/service", c.GetAllServicesPublic)
}
func (c *Controller) internal(r chi.Router) {
r.Get("/api/v1/service", c.GetAllServices)
}
func (c *Controller) GetAllServicesPublic(w http.ResponseWriter, r *http.Request) {
limit, offset, errReady := http2.ExtractLimitOffset(r)
if errReady != nil {
err := errReady.Send(w)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
return
}
return
}
items, err := c.serviceRepository.All(r.Context(), limit, offset, true)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
writeErr := http2.NewResponseErrBuilder().
WithMessage("Fetch service error").
WithStatusCode(http.StatusInternalServerError).
Send(w, r)
if writeErr != nil {
log.Global.Get(log.SERVER).Error(writeErr)
}
return
}
err = http2.JSON(w, transform.PublicServices(items...), http.StatusOK)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
}
}
func (c *Controller) GetAllServices(w http.ResponseWriter, r *http.Request) {
limit, offset, errReady := http2.ExtractLimitOffset(r)
if errReady != nil {
err := errReady.Send(w)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
return
}
return
}
items, err := c.serviceRepository.All(r.Context(), limit, offset, false)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
writeErr := http2.NewResponseErrBuilder().
WithMessage("Fetch service error").
WithStatusCode(http.StatusInternalServerError).
Send(w, r)
if writeErr != nil {
log.Global.Get(log.SERVER).Error(writeErr)
}
return
}
err = http2.JSON(w, items, http.StatusOK)
if err != nil {
log.Global.Get(log.SERVER).Error(err)
}
}
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
return nil, nil
}

99
router/init.go Normal file
View File

@@ -0,0 +1,99 @@
package router
import (
"fmt"
"maps"
"time"
"git.ostiwe.com/ostiwe-com/status/modules/log"
"git.ostiwe.com/ostiwe-com/status/router/controller"
"git.ostiwe.com/ostiwe-com/status/router/controller/ping"
"git.ostiwe.com/ostiwe-com/status/router/controller/service"
"git.ostiwe.com/ostiwe-com/status/version"
"github.com/go-andiamo/chioas"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func getControllers() []controller.Controller {
return []controller.Controller{
ping.Controller{}.New(),
service.Controller{}.New(),
}
}
func InitRoutes() *chi.Mux {
log.Global.Get(log.SERVER).Info("Setting up routers")
startTime := time.Now()
httpLogger := middleware.RequestLogger(&middleware.DefaultLogFormatter{Logger: log.Global.Get(log.SERVER), NoColor: false})
r := chi.NewRouter()
r.Use(httpLogger)
r.Use(
middleware.RequestID,
middleware.RealIP,
middleware.StripSlashes,
middleware.Recoverer,
middleware.CleanPath,
middleware.Timeout(15*time.Second),
)
ctrlList := getControllers()
for _, ctrl := range ctrlList {
r.Group(ctrl.Group)
}
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Initialized %d routers", len(ctrlList)))
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Setting up routers is done for %dms, start server", time.Since(startTime).Milliseconds()))
return r
}
func Documentate() chioas.Definition {
ctrlList := getControllers()
apiDoc := chioas.Definition{
AutoHeadMethods: true,
DocOptions: chioas.DocOptions{
ServeDocs: true,
HideHeadMethods: true,
},
Info: chioas.Info{
Version: version.AppVersion(),
Title: "Status page API Documentation",
},
Paths: make(chioas.Paths),
Components: &chioas.Components{
Schemas: make(chioas.Schemas, 0),
Requests: make(chioas.CommonRequests),
Responses: make(chioas.CommonResponses),
Examples: make(chioas.Examples, 0),
Parameters: make(chioas.CommonParameters),
SecuritySchemes: make(chioas.SecuritySchemes, 0),
Extensions: make(chioas.Extensions),
},
}
for _, ctrl := range ctrlList {
documentatePaths, components := ctrl.Documentate()
if documentatePaths != nil {
for path, pathDoc := range *documentatePaths {
apiDoc.Paths[path] = pathDoc
}
}
if components != nil {
apiDoc.Components.Schemas = append(apiDoc.Components.Schemas, components.Schemas...)
apiDoc.Components.Examples = append(apiDoc.Components.Examples, components.Examples...)
apiDoc.Components.SecuritySchemes = append(apiDoc.Components.SecuritySchemes, components.SecuritySchemes...)
maps.Copy(apiDoc.Components.Requests, components.Requests)
maps.Copy(apiDoc.Components.Responses, components.Responses)
maps.Copy(apiDoc.Components.Parameters, components.Parameters)
maps.Copy(apiDoc.Components.Extensions, components.Extensions)
}
}
return apiDoc
}