121 lines
3.6 KiB
Go
121 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"gralias/config"
|
|
"gralias/crons"
|
|
"gralias/handlers"
|
|
"gralias/repos"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
var cfg *config.Config
|
|
|
|
func init() {
|
|
cfg = config.LoadConfigOrDefault("")
|
|
}
|
|
|
|
// GzipFileServer serves pre-compressed .gz files if available
|
|
func GzipFileServer(root http.FileSystem) http.Handler {
|
|
fs := http.FileServer(root)
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Check if client accepts gzip
|
|
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
|
// Check for .gz version of the file
|
|
gzPath := r.URL.Path + ".gz"
|
|
if file, err := root.Open(gzPath); err == nil {
|
|
file.Close()
|
|
// Set headers for gzip
|
|
w.Header().Set("Content-Encoding", "gzip")
|
|
w.Header().Set("Content-Type", getContentType(r.URL.Path))
|
|
r.URL.Path = gzPath
|
|
}
|
|
}
|
|
fs.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
// Helper to set correct Content-Type
|
|
func getContentType(path string) string {
|
|
switch filepath.Ext(path) {
|
|
case ".css":
|
|
return "text/css"
|
|
case ".js":
|
|
return "application/javascript"
|
|
default:
|
|
return "" // http.FileServer will detect it
|
|
}
|
|
}
|
|
|
|
func ListenToRequests(port string) *http.Server {
|
|
mux := http.NewServeMux()
|
|
server := &http.Server{
|
|
Handler: handlers.LogRequests(handlers.GetSession(mux)),
|
|
Addr: ":" + port,
|
|
// ReadTimeout: time.Second * 5, // does this timeout conflict with sse connection?
|
|
WriteTimeout: 0, // sse streaming
|
|
}
|
|
// fs := http.FileServer(http.Dir("assets/"))
|
|
fs := http.Dir("assets/")
|
|
mux.Handle("GET /assets/", http.StripPrefix("/assets/", GzipFileServer(fs)))
|
|
//
|
|
mux.HandleFunc("GET /ping", handlers.HandlePing)
|
|
mux.HandleFunc("GET /", handlers.HandleHome)
|
|
mux.HandleFunc("GET /stats", handlers.HandleStats)
|
|
mux.HandleFunc("POST /login", handlers.HandleFrontLogin)
|
|
mux.HandleFunc("GET /signout", handlers.HandleSignout)
|
|
mux.HandleFunc("POST /join-team", handlers.HandleJoinTeam)
|
|
mux.HandleFunc("GET /end-turn", handlers.HandleEndTurn)
|
|
mux.HandleFunc("POST /room-create", handlers.HandleCreateRoom)
|
|
mux.HandleFunc("GET /start-game", handlers.HandleStartGame)
|
|
mux.HandleFunc("GET /room-join", handlers.HandleJoinRoom)
|
|
mux.HandleFunc("POST /give-clue", handlers.HandleGiveClue)
|
|
mux.HandleFunc("GET /room/exit", handlers.HandleExit)
|
|
//elements
|
|
mux.HandleFunc("GET /actionhistory", handlers.HandleActionHistory)
|
|
mux.HandleFunc("GET /room/createform", handlers.HandleShowCreateForm)
|
|
mux.HandleFunc("GET /room/hideform", handlers.HandleHideCreateForm)
|
|
mux.HandleFunc("GET /word/show-color", handlers.HandleShowColor)
|
|
mux.HandleFunc("POST /check/name", handlers.HandleNameCheck)
|
|
mux.HandleFunc("GET /add-bot", handlers.HandleAddBot)
|
|
mux.HandleFunc("GET /remove-bot", handlers.HandleRemoveBot)
|
|
mux.HandleFunc("GET /mark-card", handlers.HandleMarkCard)
|
|
// special
|
|
mux.HandleFunc("GET /renotify-bot", handlers.HandleRenotifyBot)
|
|
// sse
|
|
mux.Handle("GET /sub/sse", handlers.Notifier)
|
|
slog.Info("Listening", "addr", port)
|
|
return server
|
|
}
|
|
|
|
func main() {
|
|
// Setup graceful shutdown
|
|
stop := make(chan os.Signal, 1)
|
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
|
// repo := repos.NewRepoProvider(cfg.DBPath)
|
|
repo := repos.RP
|
|
defer repo.Close()
|
|
cm := crons.NewCronManager(repo, slog.Default())
|
|
cm.Start()
|
|
server := ListenToRequests(cfg.ServerConfig.Port)
|
|
go func() {
|
|
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
panic(err)
|
|
}
|
|
}()
|
|
<-stop
|
|
slog.Info("Shutting down server...")
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
if err := server.Shutdown(ctx); err != nil {
|
|
slog.Error("server shutdown failed", "error", err)
|
|
}
|
|
}
|