package main import ( "log/slog" "net/http" "os" "url-shortener/internal/config" "url-shortener/internal/http-server/handlers/url/redirect" "url-shortener/internal/http-server/handlers/url/save" mwLogger "url-shortener/internal/http-server/middleware/logger" "url-shortener/internal/lib/logger/handlers/slogpretty" "url-shortener/internal/lib/logger/sl" "url-shortener/internal/storage/sqlite" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) const ( envLocal = "local" envDev = "dev" envProd = "prod" ) func main() { // init config conf := config.MustLoad() // init logger log := setupLogger(conf.Env) log.Info("starting url-shortener", slog.String("env", conf.Env)) log.Debug("debug messages are enabled") // init storage storage, err := sqlite.New(conf.StoragePath) if err != nil { log.Error("failed to init storage", sl.Err(err)) os.Exit(1) } // init router router := chi.NewRouter() router.Use(middleware.RequestID) router.Use(mwLogger.New(log)) router.Use(middleware.Recoverer) router.Use(middleware.URLFormat) router.Route("/url", func(r chi.Router) { r.Use(middleware.BasicAuth("url-shortener", map[string]string{ conf.Admin.User: conf.Admin.Password, })) r.Post("/", save.New(log, storage)) }) router.Get("/{alias}", redirect.New(log, storage)) log.Info("Starting server", slog.String("address", conf.Address)) srv := &http.Server{ Addr: conf.HTTPServer.Address, Handler: router, ReadTimeout: conf.HTTPServer.Timeout, WriteTimeout: conf.HTTPServer.Timeout, IdleTimeout: conf.HTTPServer.IdleTimeout, } if err = srv.ListenAndServe(); err != nil { log.Error("failed to start server", sl.Err(err)) } log.Error("server stopped") } func setupLogger(env string) *slog.Logger { var log *slog.Logger switch env { case envLocal: log = setupPrettySlog() case envDev: log = slog.New( slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}), ) case envProd: log = slog.New( slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}), ) } return log } func setupPrettySlog() *slog.Logger { opts := slogpretty.PrettyHandlerOptions{ SlogOpts: &slog.HandlerOptions{ Level: slog.LevelDebug, }, } handler := opts.NewPrettyHandler(os.Stdout) return slog.New(handler) }