bluebell/cmd/site-hosting/main.go

131 lines
2.8 KiB
Go
Raw Normal View History

2023-07-22 00:59:45 +01:00
package main
import (
2024-08-10 13:28:30 +01:00
"context"
"errors"
2023-07-22 00:59:45 +01:00
"flag"
2024-08-10 13:28:30 +01:00
"github.com/1f349/bluebell/conf"
"github.com/1f349/bluebell/logger"
"github.com/1f349/bluebell/serve"
"github.com/1f349/bluebell/upload"
"github.com/charmbracelet/log"
"github.com/cloudflare/tableflip"
2023-07-22 00:59:45 +01:00
"github.com/julienschmidt/httprouter"
2023-08-21 00:27:54 +01:00
"github.com/spf13/afero"
2024-08-10 13:28:30 +01:00
"gopkg.in/yaml.v3"
2023-07-22 00:59:45 +01:00
"net/http"
"os"
"os/signal"
2024-08-10 13:28:30 +01:00
"path/filepath"
2023-07-22 00:59:45 +01:00
"syscall"
"time"
)
var (
2024-08-10 13:28:30 +01:00
configPath = flag.String("conf", "", "Config file path")
debugLog = flag.Bool("debug", false, "Enable debug logging")
pidFile = flag.String("pid-file", "", "Path to pid file")
2023-07-22 00:59:45 +01:00
)
func main() {
flag.Parse()
2024-08-10 13:28:30 +01:00
if *debugLog {
logger.Logger.SetLevel(log.DebugLevel)
}
logger.Logger.Info("Starting...")
2024-08-10 13:28:30 +01:00
upg, err := tableflip.New(tableflip.Options{
PIDFile: *pidFile,
})
if err != nil {
panic(err)
2023-07-22 00:59:45 +01:00
}
2024-08-10 13:28:30 +01:00
defer upg.Stop()
if *configPath == "" {
logger.Logger.Error("Config flag is missing")
os.Exit(1)
2023-07-22 00:59:45 +01:00
}
2024-08-10 13:28:30 +01:00
openConf, err := os.Open(*configPath)
2023-07-22 00:59:45 +01:00
if err != nil {
2024-08-10 13:28:30 +01:00
if os.IsNotExist(err) {
logger.Logger.Error("Missing config file")
} else {
logger.Logger.Error("Open config file", "err", err)
}
os.Exit(1)
2023-07-22 00:59:45 +01:00
}
2024-08-10 13:28:30 +01:00
var config conf.Conf
err = yaml.NewDecoder(openConf).Decode(&config)
if err != nil {
logger.Logger.Error("Invalid config file", "err", err)
os.Exit(1)
}
2023-07-22 00:59:45 +01:00
2024-08-10 13:28:30 +01:00
wd := filepath.Dir(*configPath)
sitesDir := filepath.Join(wd, "sites")
2023-07-22 00:59:45 +01:00
2024-08-10 13:28:30 +01:00
_, err = os.Stat(sitesDir)
if err != nil {
logger.Logger.Fatal("Failed to find sites, does the directory exist? Error: ", err)
2023-07-22 00:59:45 +01:00
}
2024-08-10 13:28:30 +01:00
sitesFs := afero.NewBasePathFs(afero.NewOsFs(), sitesDir)
// Do an upgrade on SIGHUP
2023-07-22 00:59:45 +01:00
go func() {
2024-08-10 13:28:30 +01:00
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGHUP)
for range sig {
err := upg.Upgrade()
if err != nil {
logger.Logger.Error("Failed upgrade", "err", err)
2023-07-22 00:59:45 +01:00
}
}
}()
2024-08-10 13:28:30 +01:00
// Listen must be called before Ready
ln, err := upg.Listen("tcp", config.Listen)
if err != nil {
logger.Logger.Fatal("Listen failed", "err", err)
}
2023-08-21 00:27:54 +01:00
2024-08-10 13:28:30 +01:00
uploadHandler := upload.New(sitesFs)
serveHandler := serve.New(sitesFs)
2023-08-21 00:27:54 +01:00
2024-08-10 13:28:30 +01:00
router := httprouter.New()
router.POST("/u/:site", uploadHandler.Handle)
router.GET("/*filepath", serveHandler.Handle)
server := &http.Server{
Handler: router,
ReadTimeout: 1 * time.Minute,
ReadHeaderTimeout: 1 * time.Minute,
WriteTimeout: 1 * time.Minute,
IdleTimeout: 1 * time.Minute,
MaxHeaderBytes: 4_096_000,
}
logger.Logger.Info("HTTP server listening on", "addr", config.Listen)
2023-08-21 00:27:54 +01:00
go func() {
2024-08-10 13:28:30 +01:00
err := server.Serve(ln)
if !errors.Is(err, http.ErrServerClosed) {
logger.Logger.Fatal("Serve failed", "err", err)
2023-08-21 00:27:54 +01:00
}
}()
2023-07-22 00:59:45 +01:00
2024-08-10 13:28:30 +01:00
logger.Logger.Info("Ready")
if err := upg.Ready(); err != nil {
panic(err)
}
<-upg.Exit()
2023-07-22 00:59:45 +01:00
2024-08-10 13:28:30 +01:00
time.AfterFunc(30*time.Second, func() {
logger.Logger.Warn("Graceful shutdown timed out")
os.Exit(1)
})
2023-07-22 00:59:45 +01:00
2024-08-10 13:28:30 +01:00
server.Shutdown(context.Background())
2023-07-22 00:59:45 +01:00
}