package httpserver import ( "context" "database/sql" "errors" "net/http" "time" echo "github.com/labstack/echo/v4" "github.com/sirupsen/logrus" "git.janky.solutions/finn/lockserver/config" "git.janky.solutions/finn/lockserver/frontend" "git.janky.solutions/finn/lockserver/zwavejs" ) var server *echo.Echo type lockserver struct { ZWaveJS *zwavejs.Client } func ListenAndServe(client *zwavejs.Client) { server = echo.New() server.HideBanner = true server.HidePort = true server.HTTPErrorHandler = handleError server.Use(accessLogMiddleware) server.StaticFS("/static", frontend.Static) server.GET("/", indexHandler) server.GET("/locks/{id}", lockHandler) logrus.WithField("address", config.C.HTTPBind).Info("starting http server") err := server.Start(config.C.HTTPBind) if err != http.ErrServerClosed { logrus.WithError(err).Fatal("error starting http server") } } func handleError(err error, c echo.Context) { if errors.Is(err, sql.ErrNoRows) { _ = c.JSON(http.StatusNotFound, map[string]string{"error": "not found"}) return } logrus.WithFields(logrus.Fields{ "path": c.Request().URL.Path, "method": c.Request().Method, "error": err, }).Error("error handling request") _ = c.JSON(http.StatusInternalServerError, map[string]string{"error": "internal server error"}) } func Shutdown(ctx context.Context) error { if server == nil { return nil } return server.Shutdown(ctx) } func accessLogMiddleware(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { start := time.Now() err := next(c) log := logrus.WithFields(logrus.Fields{ "method": c.Request().Method, "path": c.Request().URL.Path, "duration": time.Since(start), "status": c.Response().Status, "source": c.Request().RemoteAddr, }) if err != nil { log = log.WithError(err) } log.Info("request handled") return err } }