WIP
- commit
- d3164d2d32c1a37b4dd48abfbe70bf8e0b2ade71
- author
- bnema · · 2023-09-06 18:23 UTC
- committer
- bnema · · 2023-09-06 20:27 UTC
- parent
- 248c044
- signature
- unsigned
3 files · +37 -3
M internal/http/handlers/htmx-installer.go +33 -2
| @@ -1,14 +1,20 @@ | |||
| 1 | 1 | package handlers | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "fmt" | |
| 5 | + | "net/http" | |
| 6 | + | ||
| 4 | 7 | "github.com/labstack/echo/v4" | |
| 5 | 8 | "gogs.bnema.dev/gordon-echo/internal/app" | |
| 6 | 9 | "gogs.bnema.dev/gordon-echo/pkg/scripts" | |
| 7 | 10 | ) | |
| 8 | 11 | ||
| 12 | + | var eventsChan = make(chan string) | |
| 13 | + | ||
| 9 | 14 | // TraefikInstallerHandler handles the installation of Traefik | |
| 10 | 15 | func TraefikInstallerHandler(c echo.Context, a *app.App) error { | |
| 11 | 16 | logger := a.AppLogger | |
| 17 | + | eventsChan <- "Starting Traefik installation..." | |
| 12 | 18 | // Retrieve the logger from the context | |
| 13 | 19 | // Reject POST requests if they are not allowed with the RejectPOSTPolicy function | |
| 14 | 20 | if err := RejectPOSTPolicy(c); err != nil { | |
| @@ -36,9 +42,34 @@ func TraefikInstallerHandler(c echo.Context, a *app.App) error { | |||
| 36 | 42 | logger.Error().Msg("Failed to install Traefik") | |
| 37 | 43 | return err | |
| 38 | 44 | } else { | |
| 39 | - | logger.Info().Msg("Traefik installed successfully") | |
| 45 | + | eventsChan <- "Traefik installation completed!" | |
| 40 | 46 | return c.String(200, "Traefik installed successfully") | |
| 41 | 47 | } | |
| 42 | 48 | } | |
| 43 | 49 | ||
| 44 | - | // use the handler at the route /admin/install/traefik | |
| 50 | + | func TraefikInstallerSSEHandler(c echo.Context, a *app.App) error { | |
| 51 | + | w := c.Response().Writer | |
| 52 | + | flusher, ok := w.(http.Flusher) | |
| 53 | + | if !ok { | |
| 54 | + | return c.String(http.StatusInternalServerError, "Streaming unsupported!") | |
| 55 | + | } | |
| 56 | + | ||
| 57 | + | c.Response().Header().Set("Content-Type", "text/event-stream") | |
| 58 | + | c.Response().Header().Set("Cache-Control", "no-cache") | |
| 59 | + | c.Response().Header().Set("Connection", "keep-alive") | |
| 60 | + | ||
| 61 | + | for { | |
| 62 | + | // Listen for a new message to be sent to the client | |
| 63 | + | msg, open := <-eventsChan | |
| 64 | + | if !open { | |
| 65 | + | fmt.Println("Connection closed") | |
| 66 | + | break | |
| 67 | + | } | |
| 68 | + | _, err := fmt.Fprintf(w, "data: %s\n\n", msg) | |
| 69 | + | if err != nil { | |
| 70 | + | return err | |
| 71 | + | } | |
| 72 | + | flusher.Flush() | |
| 73 | + | } | |
| 74 | + | return nil | |
| 75 | + | } | |
| @@ -1,14 +1,20 @@ | |||||
| 1 | package handlers | 1 | package handlers | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "fmt" | |||
| 5 | + | "net/http" | |||
| 6 | + | ||||
| 4 | "github.com/labstack/echo/v4" | 7 | "github.com/labstack/echo/v4" | ||
| 5 | "gogs.bnema.dev/gordon-echo/internal/app" | 8 | "gogs.bnema.dev/gordon-echo/internal/app" | ||
| 6 | "gogs.bnema.dev/gordon-echo/pkg/scripts" | 9 | "gogs.bnema.dev/gordon-echo/pkg/scripts" | ||
| 7 | ) | 10 | ) | ||
| 8 | 11 | ||||
| 12 | + | var eventsChan = make(chan string) | |||
| 13 | + | ||||
| 9 | // TraefikInstallerHandler handles the installation of Traefik | 14 | // TraefikInstallerHandler handles the installation of Traefik | ||
| 10 | func TraefikInstallerHandler(c echo.Context, a *app.App) error { | 15 | func TraefikInstallerHandler(c echo.Context, a *app.App) error { | ||
| 11 | logger := a.AppLogger | 16 | logger := a.AppLogger | ||
| 17 | + | eventsChan <- "Starting Traefik installation..." | |||
| 12 | // Retrieve the logger from the context | 18 | // Retrieve the logger from the context | ||
| 13 | // Reject POST requests if they are not allowed with the RejectPOSTPolicy function | 19 | // Reject POST requests if they are not allowed with the RejectPOSTPolicy function | ||
| 14 | if err := RejectPOSTPolicy(c); err != nil { | 20 | if err := RejectPOSTPolicy(c); err != nil { | ||
| @@ -36,9 +42,34 @@ func TraefikInstallerHandler(c echo.Context, a *app.App) error { | |||||
| 36 | logger.Error().Msg("Failed to install Traefik") | 42 | logger.Error().Msg("Failed to install Traefik") | ||
| 37 | return err | 43 | return err | ||
| 38 | } else { | 44 | } else { | ||
| 39 | - | logger.Info().Msg("Traefik installed successfully") | 45 | + | eventsChan <- "Traefik installation completed!" |
| 40 | return c.String(200, "Traefik installed successfully") | 46 | return c.String(200, "Traefik installed successfully") | ||
| 41 | } | 47 | } | ||
| 42 | } | 48 | } | ||
| 43 | 49 | ||||
| 44 | - | // use the handler at the route /admin/install/traefik | 50 | + | func TraefikInstallerSSEHandler(c echo.Context, a *app.App) error { |
| 51 | + | w := c.Response().Writer | |||
| 52 | + | flusher, ok := w.(http.Flusher) | |||
| 53 | + | if !ok { | |||
| 54 | + | return c.String(http.StatusInternalServerError, "Streaming unsupported!") | |||
| 55 | + | } | |||
| 56 | + | ||||
| 57 | + | c.Response().Header().Set("Content-Type", "text/event-stream") | |||
| 58 | + | c.Response().Header().Set("Cache-Control", "no-cache") | |||
| 59 | + | c.Response().Header().Set("Connection", "keep-alive") | |||
| 60 | + | ||||
| 61 | + | for { | |||
| 62 | + | // Listen for a new message to be sent to the client | |||
| 63 | + | msg, open := <-eventsChan | |||
| 64 | + | if !open { | |||
| 65 | + | fmt.Println("Connection closed") | |||
| 66 | + | break | |||
| 67 | + | } | |||
| 68 | + | _, err := fmt.Fprintf(w, "data: %s\n\n", msg) | |||
| 69 | + | if err != nil { | |||
| 70 | + | return err | |||
| 71 | + | } | |||
| 72 | + | flusher.Flush() | |||
| 73 | + | } | |||
| 74 | + | return nil | |||
| 75 | + | } | |||
M internal/http/routes/router.go +3 -0
| @@ -36,6 +36,9 @@ func bindAdminRoutes(e *echo.Echo, a *app.App, ac *app.Config) *echo.Echo { | |||
| 36 | 36 | e.POST("/admin/install/traefik", func(c echo.Context) error { | |
| 37 | 37 | return handlers.TraefikInstallerHandler(c, a) | |
| 38 | 38 | }) | |
| 39 | + | e.GET("/admin/install/traefik/sse", func(c echo.Context) error { | |
| 40 | + | return handlers.TraefikInstallerSSEHandler(c, a) | |
| 41 | + | }) | |
| 39 | 42 | return e | |
| 40 | 43 | } | |
| 41 | 44 | ||
| @@ -36,6 +36,9 @@ func bindAdminRoutes(e *echo.Echo, a *app.App, ac *app.Config) *echo.Echo { | |||||
| 36 | e.POST("/admin/install/traefik", func(c echo.Context) error { | 36 | e.POST("/admin/install/traefik", func(c echo.Context) error { | ||
| 37 | return handlers.TraefikInstallerHandler(c, a) | 37 | return handlers.TraefikInstallerHandler(c, a) | ||
| 38 | }) | 38 | }) | ||
| 39 | + | e.GET("/admin/install/traefik/sse", func(c echo.Context) error { | |||
| 40 | + | return handlers.TraefikInstallerSSEHandler(c, a) | |||
| 41 | + | }) | |||
| 39 | return e | 42 | return e | ||
| 40 | } | 43 | } | ||
| 41 | 44 | ||||
M internal/ui/templates/install.gohtml +1 -1
| @@ -100,7 +100,7 @@ | |||
| 100 | 100 | <div | |
| 101 | 101 | class="flex flex-col space-y-2" | |
| 102 | 102 | hx-ext="sse" | |
| 103 | - | sse-connect="/install/traefik/sse" | |
| 103 | + | sse-connect="/admin/install/traefik/sse" | |
| 104 | 104 | > | |
| 105 | 105 | <!-- One item --> | |
| 106 | 106 | <div class="flex flex-row items-center"> | |
| @@ -100,7 +100,7 @@ | |||||
| 100 | <div | 100 | <div | ||
| 101 | class="flex flex-col space-y-2" | 101 | class="flex flex-col space-y-2" | ||
| 102 | hx-ext="sse" | 102 | hx-ext="sse" | ||
| 103 | - | sse-connect="/install/traefik/sse" | 103 | + | sse-connect="/admin/install/traefik/sse" |
| 104 | > | 104 | > | ||
| 105 | <!-- One item --> | 105 | <!-- One item --> | ||
| 106 | <div class="flex flex-row items-center"> | 106 | <div class="flex flex-row items-center"> | ||