/*
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* 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)
}
}