feat: improve log viewer with auto-scroll and security enhancements
- Add auto-scroll toggle to log panels - Enhance SSE connection handling with reconnection logic - Improve HTML escaping in log lines for security - Update build script to properly handle frontend artifacts - Add graceful shutdown to backend server - Update authentication to support configurable username
This commit is contained in:
Vendored
+1
@@ -0,0 +1 @@
|
||||
Placeholder for embed
|
||||
+22
-3
@@ -10,8 +10,10 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/hpcloud/tail"
|
||||
)
|
||||
@@ -23,12 +25,14 @@ var staticFiles embed.FS
|
||||
var (
|
||||
port string
|
||||
password string
|
||||
username string
|
||||
)
|
||||
|
||||
// init() é executado antes de main(). É o lugar ideal para configurar flags.
|
||||
func init() {
|
||||
flag.StringVar(&port, "port", ":8080", "Porta para o servidor web (ex: :8080, 9090)")
|
||||
flag.StringVar(&password, "password", "", "Senha para autenticar o acesso à interface web")
|
||||
flag.StringVar(&username, "username", "admin", "Nome de usuário para autenticar o acesso à interface web")
|
||||
}
|
||||
|
||||
// LogEntry representa uma linha de log
|
||||
@@ -88,7 +92,9 @@ func handleSSE(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "http://localhost:8080")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
|
||||
clientChan := broker.Subscribe()
|
||||
defer broker.Unsubscribe(clientChan)
|
||||
@@ -96,7 +102,11 @@ func handleSSE(w http.ResponseWriter, r *http.Request) {
|
||||
for {
|
||||
select {
|
||||
case entry := <-clientChan:
|
||||
data, _ := json.Marshal(entry)
|
||||
data, err := json.Marshal(entry)
|
||||
if err != nil {
|
||||
log.Printf("Erro ao serializar entrada de log: %v", err)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "data: %s\n\n", data)
|
||||
flusher.Flush()
|
||||
case <-r.Context().Done():
|
||||
@@ -155,7 +165,7 @@ func authMiddleware(next http.Handler) http.Handler {
|
||||
requestAuth(w)
|
||||
return
|
||||
}
|
||||
usernameMatch := subtle.ConstantTimeCompare([]byte(user), []byte("admin")) == 1
|
||||
usernameMatch := subtle.ConstantTimeCompare([]byte(user), []byte(username)) == 1
|
||||
passwordMatch := subtle.ConstantTimeCompare([]byte(pass), []byte(password)) == 1
|
||||
if usernameMatch && passwordMatch {
|
||||
next.ServeHTTP(w, r)
|
||||
@@ -182,6 +192,15 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Configurar tratamento de sinais para desligamento gracioso
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
sig := <-sigChan
|
||||
log.Printf("Recebido sinal %v, encerrando servidor...", sig)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
startTailing(logFiles)
|
||||
|
||||
distFS, err := fs.Sub(staticFiles, "dist")
|
||||
|
||||
Reference in New Issue
Block a user