web/server.go
2025-03-27 09:19:08 +01:00

116 lines
2.2 KiB
Go

package webserver
import (
"context"
"fmt"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"log/slog"
"net"
"net/http"
"syscall"
"time"
)
type Server struct {
module *Module
listener *net.Listener
csrfConfig *middleware.CSRFConfig
router *echo.Echo
server *http.Server
}
func NewServer(module *Module) *Server {
s := &Server{
module: module,
}
s.init()
return s
}
func (s *Server) init() {
s.csrfConfig = &middleware.CSRFConfig{
TokenLookup: "form:_csrf,query:csrf,header:X-CSRF-Token",
}
s.router = echo.New()
//s.router.Pre(middleware.RemoveTrailingSlash())
s.router.Use(middleware.Logger())
s.router.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
LogLevel: 4,
}))
s.router.Use(middleware.CSRFWithConfig(*s.csrfConfig))
s.router.Use(CustomContext(s.csrfConfig))
if s.module.moduleConfig != nil && s.module.moduleConfig.Middlewares != nil {
for _, m := range s.module.moduleConfig.Middlewares {
s.router.Use(m())
}
}
tplFS := s.module.getTemplatesFS()
s.router.Renderer = NewRenderer(tplFS)
s.router.StaticFS("/static", s.module.getStaticFS())
}
func (s *Server) Start() error {
config := &net.ListenConfig{Control: s.reusePort}
listener, err := config.Listen(
context.Background(),
"tcp",
fmt.Sprintf(":%d", s.module.config.Port),
)
if err != nil {
return err
}
s.listener = &listener
s.server = &http.Server{
Addr: fmt.Sprintf(":%d", s.module.config.Port),
Handler: s.router,
}
go s.server.Serve(listener)
return nil
}
func (s *Server) Stop() error {
if s.server == nil {
return nil
}
timeout := 10 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return s.server.Shutdown(ctx)
}
func (s *Server) GetGroup() *Group {
return &Group{
s.router.Group("/"),
}
}
func (s *Server) GetRenderer() *Renderer {
return s.router.Renderer.(*Renderer)
}
func (s *Server) reusePort(network, address string, conn syscall.RawConn) error {
return conn.Control(func(descriptor uintptr) {
err := syscall.SetsockoptInt(int(descriptor), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
if err != nil {
slog.Error("error during setting reuseport", err)
}
})
}