url_shortener/cmd/url-shortener/main.go

105 lines
2.3 KiB
Go

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)
}