package main import ( "crypto/tls" "database/sql" "flag" "html/template" "log" "net/http" "os" "time" "gitea.local.lab/Lbenedar/snippetbox/internal/models" "github.com/alexedwards/scs/mysqlstore" "github.com/alexedwards/scs/v2" "github.com/go-playground/form/v4" _ "github.com/go-sql-driver/mysql" ) type application struct { errorLog *log.Logger infoLog *log.Logger snippets models.SnippetModelInterface users models.UserModelInterface templateCache map[string]*template.Template formDecoder *form.Decoder sessionManager *scs.SessionManager } type config struct { addr string staticDir string dsn string } func main() { var cfg config flag.StringVar(&cfg.addr, "addr", ":4000", "HTTP network address") flag.StringVar(&cfg.staticDir, "static-dir", "./ui/static", "Path to static assets") flag.StringVar(&cfg.dsn, "dsn", "web:pass@/snippetbox?parseTime=true", "MySQL data source name") flag.Parse() errorLog := log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile) infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime) db, err := openDB(cfg.dsn) if err != nil { errorLog.Fatal(err) } defer db.Close() templateCache, err := newTemplateCache() if err != nil { errorLog.Fatal(err) } formDecoder := form.NewDecoder() sessionManager := scs.New() sessionManager.Store = mysqlstore.New(db) sessionManager.Lifetime = 12 * time.Hour app := &application{ errorLog: errorLog, infoLog: infoLog, 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}, // TODO: read about CurvePreferences } srv := &http.Server{ Addr: cfg.addr, ErrorLog: errorLog, Handler: app.routes(), TLSConfig: tlsConfig, IdleTimeout: time.Minute, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } infoLog.Printf("Starting server on %s", cfg.addr) err = srv.ListenAndServeTLS("./tls/cert.pem", "./tls/key.pem") errorLog.Fatal(err) } func openDB(dsn string) (*sql.DB, error) { db, err := sql.Open("mysql", dsn) if err != nil { return nil, err } if err = db.Ping(); err != nil { return nil, err } return db, nil }