gocustomurls/main.go

189 lines
4.6 KiB
Go

package main
import (
"context"
"errors"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"
)
var errorLog *log.Logger = log.New(os.Stderr, "", log.LstdFlags)
// const (
// DEFAULT_RULES_FILE string = "/var/lib/gocustomurls/rules.json"
// DEFAULT_LOG_FILE string = "/var/log/gocustomurls/app.log"
// )
// flagsSet returns a set of all the flags what were actually set on the
// command line.
func flagsSet(flags *flag.FlagSet) map[string]bool {
s := make(map[string]bool)
flags.Visit(func(f *flag.Flag) {
s[f.Name] = true
})
return s
}
// generateDefaults - generate the default values for the rules.json and log files
// func generateDefaults(rulesfp string, logfp string) (string, string, error) {
// var newlogfp, newrulesfp string
// var err error
// newlogfp = logfp
// newrulesfp = rulesfp
// if len(newrulesfp) == 0 {
// dir, err := os.UserConfigDir()
// if err != nil {
// return newrulesfp, newlogfp, err
// }
// newrulesfp = filepath.Join(dir, "gocustomcurls", "rules.json")
// }
// if len(newlogfp) == 0 {
// dir, err := os.UserHomeDir()
// if err != nil {
// return newrulesfp, newlogfp, err
// }
// newlogfp = filepath.Join(dir, ".gocustomurls", "logs", "app.log")
// }
// return newrulesfp, newlogfp, err
// }
// isValidPort returns true if the port is valid
// following the RFC https://datatracker.ietf.org/doc/html/rfc6056#section-2.1
func isValidPort(port int) bool {
return port > 0 && port < 65535
}
func main() {
programName := os.Args[0]
// errorLog = log.New(os.Stderr, "", log.LstdFlags)
flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
flags.Usage = func() {
out := flags.Output()
fmt.Fprintf(out, "Usage: %v [flags]\n\n", programName)
fmt.Fprint(out, " This utility serves vanity urls for the go get/install command.\n")
fmt.Fprint(out, " By default, the server listens on localhost:7070.\n")
flags.PrintDefaults()
}
confFlag := flags.String("conf", "", "Required. Contains all the configurations options")
// portFlag := flags.String("port", "7070", "Optional. Default port is 7070. Port to listen to")
// rulesFileFlag := flags.String("rules", "", "Optional. Contains go-import mapping")
// logFileFlag := flags.String("logfile", "", "Optional. Default log file")
flags.Parse(os.Args[1:])
if len(flags.Args()) > 1 {
errorLog.Println("Error: too many command-line arguments")
flags.Usage()
os.Exit(1)
}
allSetFlags := flagsSet(flags)
if !allSetFlags["conf"] {
errorLog.Println("Error: conf arguments must be set")
flags.Usage()
os.Exit(1)
}
// TODO: Use only one flag conf with a conf file that
// contains the following configuration, port, logfile, rulesfile, sizeofRotation
conf := *confFlag
c := &Config{}
pConf, err := c.LoadMainConfigFile(conf)
if err != nil {
errorLog.Println(err)
os.Exit(1)
}
p, err := strconv.Atoi(pConf.Port)
if err != nil {
errorLog.Println(err)
os.Exit(1)
}
if !isValidPort(p) {
errorLog.Println(fmt.Errorf("provided port (%d) is not valid", p))
os.Exit(1)
}
err = c.LoadMappingFile(pConf.RulesFp)
if err != nil {
errorLog.Println(err)
os.Exit(1)
}
l, err := newFileLogger(pConf.LogFp, pConf.SizeToRotate, pConf.Compression)
if err != nil {
errorLog.Println(err)
os.Exit(1)
}
// var rulesFile string
// if allSetFlags["config"] {
// rulesFile = *rulesFileFlag
// }
// var logFile string
// if allSetFlags["logFile"] {
// logFile = *logFileFlag
// }
// rFile, lFile, err := generateDefaults(logFile, rulesFile)
// if err != nil {
// errorLog.Println(err)
// os.Exit(1)
// }
// // load rules mapping
// c := &Config{}
// err = c.LoadMappingFile(rFile)
// if err != nil {
// errorLog.Println(err)
// os.Exit(1)
// }
// l, err := newFileLogger(lFile)
// if err != nil {
// errorLog.Println(err)
// os.Exit(1)
// }
app := &Application{
Config: c,
Log: l,
}
srv := app.Setup(pConf.Port)
// For graceful shutdowns
go func() {
app.Log.logger.Printf("%s Starting\n", getCurrentDate())
err := srv.ListenAndServe()
if !errors.Is(err, http.ErrServerClosed) {
errorLog.Printf("HTTP Server error: %+v\n", err)
os.Exit(1)
}
app.Log.logger.Printf("%s Stopped serving new connections.\n", getCurrentDate())
}()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), 10*time.Second)
defer shutdownRelease()
if err := srv.Shutdown(shutdownCtx); err != nil {
errorLog.Printf("HTTP shutdown error: %+v\n", err)
os.Exit(1)
}
app.Log.logger.Printf("%s Graceful shutdown complete.\n", getCurrentDate())
}