/* * Copyright (C) 2023 Jonni Liljamo * * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for * more information. */ package main import ( "fmt" "log" "net/http" "strconv" "time" "git.src.quest/~skye/felu-ddns/config" "git.src.quest/~skye/felu-ddns/db" "git.src.quest/~skye/felu-ddns/dns" "github.com/gin-gonic/gin" "golang.org/x/sync/errgroup" ) var version = "notset-builtin" var ( g errgroup.Group ) func ginLogFormat(param gin.LogFormatterParams, router string) string { var statusColor, methodColor, resetColor string if param.IsOutputColor() { statusColor = param.StatusCodeColor() methodColor = param.MethodColor() resetColor = param.ResetColor() } if param.Latency > time.Minute { param.Latency = param.Latency.Truncate(time.Second) } return fmt.Sprintf("[GIN] [felu/%-8s] | %v |%s %3d %s| %13v | %15s |%s %-7s %s %#v\n%s", router, param.TimeStamp.Format("2006/01/02 - 15:04:05"), statusColor, param.StatusCode, resetColor, param.Latency, param.ClientIP, methodColor, param.Method, resetColor, param.Path, param.ErrorMessage, ) } func setupFrontendRouter() *gin.Engine { r := gin.New() r.Use(gin.Recovery()) r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { return ginLogFormat(param, "frontend") })) r.Static("/static", "./static") r.HTMLRender = &TemplRender{} r.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "", index()) }) return r } func setupBackendRouter() *gin.Engine { r := gin.New() r.Use(gin.Recovery()) r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { return ginLogFormat(param, "backend") })) r.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "success", }) }) r.GET("/version", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "version": version, }) }) return r } func main() { log.Print("[felu] Starting up...") config.InitConfig() if err := db.InitDB(); err != nil { log.Fatalf("[felu] Failed to initialize database: '%s'", err) } defer db.DBConn.Close() frontend := &http.Server{ Addr: config.FeluConfig.FrontendBindAddr, Handler: setupFrontendRouter(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } backend := &http.Server{ Addr: config.FeluConfig.BackendBindAddr, Handler: setupBackendRouter(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } log.Printf("[felu] Serving frontend at '%s'", config.FeluConfig.FrontendBindAddr) g.Go(func() error { return frontend.ListenAndServe() }) log.Printf("[felu] Serving backend at '%s'", config.FeluConfig.BackendBindAddr) g.Go(func() error { return backend.ListenAndServe() }) dnsIP := config.FeluConfig.DNSBindIP dnsPort := strconv.Itoa(int(config.FeluConfig.DNSBindPort)) dnsAddr := dnsIP + ":" + dnsPort log.Printf("[felu] Serving DNS at '%s'", dnsAddr) g.Go(func() error { return dns.Run(dnsAddr) }) if err := g.Wait(); err != nil { log.Fatalf("[felu] Error while running: %s", err) } }