mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-07 08:34:15 +01:00
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
|
package api
|
||
|
|
||
|
import (
|
||
|
"io/fs"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
|
||
|
"github.com/TwiN/gatus/v5/config"
|
||
|
static "github.com/TwiN/gatus/v5/web"
|
||
|
"github.com/TwiN/health"
|
||
|
fiber "github.com/gofiber/fiber/v2"
|
||
|
"github.com/gofiber/fiber/v2/middleware/adaptor"
|
||
|
"github.com/gofiber/fiber/v2/middleware/compress"
|
||
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||
|
fiberfs "github.com/gofiber/fiber/v2/middleware/filesystem"
|
||
|
"github.com/gofiber/fiber/v2/middleware/recover"
|
||
|
"github.com/gofiber/fiber/v2/middleware/redirect"
|
||
|
"github.com/prometheus/client_golang/prometheus"
|
||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||
|
)
|
||
|
|
||
|
type API struct {
|
||
|
router *fiber.App
|
||
|
}
|
||
|
|
||
|
func New(cfg *config.Config) *API {
|
||
|
api := &API{}
|
||
|
api.router = api.createRouter(cfg)
|
||
|
return api
|
||
|
}
|
||
|
|
||
|
func (a *API) Router() *fiber.App {
|
||
|
return a.router
|
||
|
}
|
||
|
|
||
|
func (a *API) createRouter(cfg *config.Config) *fiber.App {
|
||
|
app := fiber.New(fiber.Config{
|
||
|
ErrorHandler: func(c *fiber.Ctx, err error) error {
|
||
|
log.Printf("[api.ErrorHandler] %s", err.Error())
|
||
|
return fiber.DefaultErrorHandler(c, err)
|
||
|
},
|
||
|
})
|
||
|
if os.Getenv("ENVIRONMENT") == "dev" {
|
||
|
app.Use(cors.New(cors.Config{
|
||
|
AllowOrigins: "http://localhost:8081",
|
||
|
AllowCredentials: true,
|
||
|
}))
|
||
|
}
|
||
|
apiRouter := app.Group("/api")
|
||
|
protectedAPIRouter := apiRouter.Group("/")
|
||
|
unprotectedAPIRouter := apiRouter.Group("/")
|
||
|
if cfg.Metrics {
|
||
|
metricsHandler := promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
|
||
|
DisableCompression: true,
|
||
|
}))
|
||
|
app.Get("/metrics", adaptor.HTTPHandler(metricsHandler))
|
||
|
}
|
||
|
// Security (ORDER IS IMPORTANT: middlewares must be applied before the routes are registered)
|
||
|
if cfg.Security != nil {
|
||
|
if err := cfg.Security.RegisterHandlers(app); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
if err := cfg.Security.ApplySecurityMiddleware(protectedAPIRouter); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|
||
|
// Middlewares
|
||
|
app.Use(recover.New())
|
||
|
app.Use(compress.New())
|
||
|
// Routes
|
||
|
handler := ConfigHandler{securityConfig: cfg.Security}
|
||
|
unprotectedAPIRouter.Get("/v1/config", handler.GetConfig)
|
||
|
protectedAPIRouter.Get("/v1/endpoints/statuses", EndpointStatuses(cfg))
|
||
|
protectedAPIRouter.Get("/v1/endpoints/:key/statuses", EndpointStatus)
|
||
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/health/badge.svg", HealthBadge)
|
||
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/uptimes/:duration/badge.svg", UptimeBadge)
|
||
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/badge.svg", ResponseTimeBadge(cfg))
|
||
|
unprotectedAPIRouter.Get("/v1/endpoints/:key/response-times/:duration/chart.svg", ResponseTimeChart)
|
||
|
// SPA
|
||
|
app.Get("/", SinglePageApplication(cfg.UI))
|
||
|
app.Get("/endpoints/:name", SinglePageApplication(cfg.UI))
|
||
|
// Health endpoint
|
||
|
healthHandler := health.Handler().WithJSON(true)
|
||
|
app.Get("/health", func(c *fiber.Ctx) error {
|
||
|
statusCode, body := healthHandler.GetResponseStatusCodeAndBody()
|
||
|
return c.Status(statusCode).Send(body)
|
||
|
})
|
||
|
// Everything else falls back on static content
|
||
|
app.Use(redirect.New(redirect.Config{
|
||
|
Rules: map[string]string{
|
||
|
"/index.html": "/",
|
||
|
},
|
||
|
StatusCode: 301,
|
||
|
}))
|
||
|
staticFileSystem, err := fs.Sub(static.FileSystem, static.RootPath)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
app.Use("/", fiberfs.New(fiberfs.Config{
|
||
|
Root: http.FS(staticFileSystem),
|
||
|
Index: "index.html",
|
||
|
Browse: true,
|
||
|
}))
|
||
|
return app
|
||
|
}
|