this repo has no description
at main 2.3 kB view raw
1package main 2 3import ( 4 "context" 5 "log/slog" 6 "net" 7 "net/http" 8 "time" 9 10 "tangled.org/bnewbold.net/scrumble/store" 11 12 "github.com/bluesky-social/indigo/atproto/identity" 13 "github.com/bluesky-social/indigo/util/svcutil" 14 "github.com/labstack/echo/v4" 15 "github.com/labstack/echo/v4/middleware" 16 "github.com/prometheus/client_golang/prometheus/promhttp" 17 "gorm.io/gorm" 18) 19 20type Server struct { 21 logger *slog.Logger 22 dir identity.Directory 23 store *store.Store 24} 25 26func NewServer(db *gorm.DB) (*Server, error) { 27 28 st, err := store.NewStore(db) 29 if err != nil { 30 return nil, err 31 } 32 33 return &Server{ 34 logger: slog.Default(), 35 dir: identity.DefaultDirectory(), 36 store: st, 37 }, nil 38} 39 40func (srv *Server) StartMetrics(listen string) error { 41 http.Handle("/metrics", promhttp.Handler()) 42 return http.ListenAndServe(listen, nil) 43} 44 45func (srv *Server) StartHTTP(bind string) error { 46 var lc net.ListenConfig 47 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 48 defer cancel() 49 50 li, err := lc.Listen(ctx, "tcp", bind) 51 if err != nil { 52 return err 53 } 54 return srv.startWithListener(li) 55} 56 57func (srv *Server) startWithListener(listen net.Listener) error { 58 e := echo.New() 59 e.HideBanner = true 60 61 e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ 62 AllowOrigins: []string{"*"}, 63 AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization}, 64 })) 65 e.Use(func(next echo.HandlerFunc) echo.HandlerFunc { 66 return func(c echo.Context) error { 67 c.Response().Header().Set(echo.HeaderServer, "ScrumbleServer") 68 return next(c) 69 } 70 }) 71 e.Use(middleware.LoggerWithConfig(middleware.DefaultLoggerConfig)) 72 73 e.File("/robots.txt", "assets/robots.txt") 74 e.Static("/assets", "assets") 75 76 e.Use(svcutil.MetricsMiddleware) 77 78 e.GET("/", srv.HandleHomeMessage) 79 e.GET("/_health", srv.HandleHealthCheck) 80 81 // In order to support booting on random ports in tests, we need to tell 82 // the Echo instance it's already got a port, and then use its StartServer 83 // method to re-use that listener. 84 e.Listener = listen 85 httpServer := &http.Server{} 86 // TODO: attach echo to Server, for shutdown? 87 return e.StartServer(httpServer) 88} 89 90func (srv *Server) Shutdown() []error { 91 var errs []error 92 93 // TODO: stop consumer 94 // TODO: stop echo 95 return errs 96}