package main import "fmt" import "os" import "time" import "net/http" import "github.com/rs/zerolog/log" import "github.com/gin-gonic/gin" import "github.com/dn365/gin-zerolog" type TootArchiverAPIServer struct { archiver *TootArchiver } func (a *TootArchiverAPIServer) Serve() { if a.archiver == nil { panic("must have archiver from which to serve stats") } s := a.getServer() err := s.ListenAndServe() if err != nil { log.Fatal().Msg("webserver failure: " + err.Error()) return } } func (a *TootArchiverAPIServer) getRouter() *gin.Engine { if os.Getenv("DEBUG") == "" { gin.SetMode(gin.ReleaseMode) } // empty router r := gin.New() // wrap panics: r.Use(gin.Recovery()) // attach logger middleware r.Use(ginzerolog.Logger("gin")) r.GET("/.well-known/healthcheck.json", func(c *gin.Context) { c.JSON(200, gin.H{ "status": "ok", "now": time.Now().UTC().Format(time.RFC3339), "uptime": a.archiver.Uptime().String(), }) }) r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ // FIXME(sneak) add more stuff here "status": "ok", "now": time.Now().UTC().Format(time.RFC3339), "uptime": a.archiver.Uptime().String(), "instances": gin.H{ "total": a.archiver.locator.instanceReport().total, "up": a.archiver.locator.instanceReport().up, "identified": a.archiver.locator.instanceReport().identified, }, }) }) // FIXME(sneak) add more status routes here return r } func (a *TootArchiverAPIServer) getServer() *http.Server { r := a.getRouter() port := "8080" if os.Getenv("PORT") != "" { port = os.Getenv("PORT") } log.Info().Str("port", port).Msg("starting webserver") s := &http.Server{ Addr: fmt.Sprintf(":%s", port), Handler: r, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } return s }