package htmlhouse import ( "database/sql" "fmt" "html/template" "io/ioutil" "net/http" "github.com/gorilla/mux" "github.com/writeas/impart" ) type app struct { cfg *config router *mux.Router db *sql.DB session sessionManager templates map[string]*template.Template } func newApp() (*app, error) { var err error app := &app{} app.cfg, err = newConfig() if err != nil { return app, err } app.session, err = newSessionManager(app.cfg) if err != nil { return app, err } err = app.initDatabase() if err != nil { return app, err } app.initTemplates() app.initRouter() return app, nil } func (app *app) close() { app.db.Close() } func (app *app) initRouter() { app.router = mux.NewRouter() api := app.router.PathPrefix("/⌂/").Subrouter() api.HandleFunc("/create", app.handler(createHouse)).Methods("POST").Name("create") api.HandleFunc("/{house:[A-Za-z0-9.-]{8}}", app.handler(renovateHouse)).Methods("POST").Name("update") app.router.HandleFunc("/", app.handler(getEditor)).Methods("GET").Name("index") app.router.HandleFunc("/edit/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getEditor)).Methods("GET").Name("edit") app.router.HandleFunc("/stats/{house:[A-Za-z0-9.-]{8}}.html", app.handler(viewHouseStats)).Methods("GET").Name("stats") app.router.HandleFunc("/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getHouse)).Methods("GET").Name("get") app.router.HandleFunc("/browse", app.handler(viewHouses)).Methods("GET").Name("browse") app.router.PathPrefix("/").Handler(http.FileServer(http.Dir(app.cfg.StaticDir))) } type EditorPage struct { ID string Content string } func getEditor(app *app, w http.ResponseWriter, r *http.Request) error { vars := mux.Vars(r) house := vars["house"] if house == "" { defaultPage, err := ioutil.ReadFile(app.cfg.StaticDir + "/default.html") if err != nil { fmt.Printf("\n%s\n", err) defaultPage = []byte("\n\n") } app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{"", string(defaultPage)}) return nil } html, err := getHouseHTML(app, house) if err != nil { return err } app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{house, html}) return nil } type handlerFunc func(app *app, w http.ResponseWriter, r *http.Request) error func (app *app) handler(h handlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { handleError(w, r, func() error { return h(app, w, r) }()) } } func handleError(w http.ResponseWriter, r *http.Request, err error) { if err == nil { return } if err, ok := err.(impart.HTTPError); ok { impart.WriteError(w, err) return } impart.WriteError(w, impart.HTTPError{http.StatusInternalServerError, "This is an unhelpful error message for a miscellaneous internal error."}) }