105 lines
2.3 KiB
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)
|
||
|
}
|