learn-go/snippetbox/cmd/web/main.go
tamsin johnson 4f2dc018da lets-go:11.0 user signup without peeking
deliberately skipping salting and encrypting passwords at this point. intending
to approach this in tandem with authenication.

also starting to want db migrations, but trying not to get distracted.
2024-02-07 11:07:29 -08:00

111 lines
2.5 KiB
Go

package main
import (
"crypto/tls"
"database/sql"
"flag"
"html/template"
"log/slog"
"net/http"
"regexp"
"os"
"time"
"snippetbox.chaosfem.tw/internal/models"
"github.com/alexedwards/scs/mysqlstore"
"github.com/alexedwards/scs/v2"
"github.com/go-playground/form/v4"
_ "github.com/go-sql-driver/mysql"
)
// for application wide dependencies
type application struct {
logger *slog.Logger
snippets *models.SnippetModel
users *models.UserModel
templateCache map[string]*template.Template
formDecoder *form.Decoder
sessionManager *scs.SessionManager
}
// main it's the snippetbox webapp
func main() {
// configuration
addr := flag.String("addr", ":4000", "HTTP network address")
dsn := flag.String("dsn", "web:dbpass@/snippetbox?parseTime=true", "DB data source name")
logfmt := flag.String("logfmt", "text", "Log output format")
loglevel := flag.String("loglevel", "INFO", "Log level: DEBUG, INFO, WARN, or ERROR")
flag.Parse()
logger := loggerBuilder(logfmt, loglevel)
db, err := openDB(*dsn, logger)
if err != nil {
logger.Error(err.Error())
os.Exit(1)
}
defer db.Close()
templateCache, err := newTemplateCache()
if err != nil {
logger.Error(err.Error())
os.Exit(1)
}
formDecoder := form.NewDecoder()
sessionManager := scs.New()
sessionManager.Store = mysqlstore.New(db)
sessionManager.Lifetime = 12 * time.Hour
// setup the application
app := &application{
logger: logger,
snippets: &models.SnippetModel{DB: db},
users: &models.UserModel{DB: db},
templateCache: templateCache,
formDecoder: formDecoder,
sessionManager: sessionManager,
}
tlsConfig := &tls.Config{
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
}
srv := &http.Server{
Addr: *addr,
Handler: app.routes(),
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
TLSConfig: tlsConfig,
IdleTimeout: time.Minute,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
logger.Info("starting server", slog.String("addr", srv.Addr))
err = srv.ListenAndServeTLS("./tls/cert.pem", "./tls/key.pem")
logger.Error(err.Error())
os.Exit(1)
}
func openDB(dsn string, logger *slog.Logger) (*sql.DB, error) {
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, err
}
err = db.Ping()
if err != nil {
db.Close()
return nil, err
}
passRegexp := regexp.MustCompile(":\\S+@")
logger.Info("Opened DB connection pool", slog.String("adapter", "mysql"), slog.String("dsn", passRegexp.ReplaceAllString(dsn, ":<REDACTED>@")))
return db, nil
}