package main import ( "context" "database/sql" "encoding/hex" "html/template" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/gorilla/securecookie" ) type handler func(DataStore, http.ResponseWriter, *http.Request) type App struct { DataStore Config *Config CookieHandler *securecookie.SecureCookie Template *template.Template } func New() *App { app := new(App) config := NewConfig() app.Config = config db, err := sql.Open("postgres", config.Database) if err = db.Ping(); err != nil { log.Fatal(err) } app.DataStore = &SqlStore{db} hashKey, err := hex.DecodeString(config.HashKey) blockKey, err := hex.DecodeString(config.BlockKey) s := securecookie.New(hashKey, blockKey) app.CookieHandler = s fmap := template.FuncMap{ "ago": ago, } templates := template.Must(template.New("").Funcs(fmap).ParseGlob("templates/*.tmpl")) app.Template = templates return app } func logg(fn http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { t := time.Now() r.ParseForm() fn(w, r) log.Println(r.Method, r.URL.Path, time.Since(t)) } } func (app *App) InitApiServer() *http.Server { apiServer := new(http.Server) sm := http.NewServeMux() sm.HandleFunc("/", logg(app.mainHandler)) sm.HandleFunc("/np", logg(app.nowPlayingHandler)) sm.HandleFunc("/scrobble", logg(app.scrobbleHandler)) sm.HandleFunc("/2.0/", logg(app.ApiHandler)) apiServer.Addr = ":3001" apiServer.Handler = sm return apiServer } func (app *App) InitWebServer() *http.Server { webServer := new(http.Server) sm := http.NewServeMux() fs := http.FileServer(http.Dir("static")) sm.Handle("/static/", http.StripPrefix("/static/", fs)) sm.HandleFunc("/", logg(app.root)) sm.HandleFunc("/callback", logg(app.callback)) sm.HandleFunc("/login", logg(app.login)) sm.HandleFunc("/settings", logg(app.settings)) webServer.Addr = ":8000" webServer.Handler = sm return webServer } func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) app := New() apiServer := app.InitApiServer() webServer := app.InitWebServer() var stop = make(chan os.Signal) signal.Notify(stop, syscall.SIGKILL) signal.Notify(stop, syscall.SIGINT) signal.Notify(stop, syscall.SIGTERM) go func() { <-stop apiServer.Shutdown(context.Background()) log.Println("Api server stopped") webServer.Shutdown(context.Background()) log.Println("Web server stopped") }() go func() { log.Printf("Api server listening on http://127.0.0.1%s\n", apiServer.Addr) apiServer.ListenAndServe() }() log.Printf("Web server listening on http://127.0.0.1%s\n", webServer.Addr) webServer.ListenAndServe() }