diff --git a/cmd/reloader/reloader.go b/cmd/reloader/reloader.go new file mode 100644 index 0000000..c462ea2 --- /dev/null +++ b/cmd/reloader/reloader.go @@ -0,0 +1,33 @@ +package main + +import ( + "flag" + "net/http" + + "code.google.com/p/rsc/devweb/slave" + + "github.com/golang/glog" + + "xinu.tv/email/db" + "xinu.tv/email/handlers" +) + +func main() { + flag.Parse() + defer glog.Flush() + + c, err := db.NewConn("") + if err != nil { + glog.Fatal(err) + } + + h := handlers.Handlers(c) + // Mount the app's mux at / so the default http server will handle them. + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + // Useful when debugging, flush logs after every request. + glog.Flush() + }) + + slave.Main() +} diff --git a/cmd/xwebmail/xwebmail.go b/cmd/xwebmail/xwebmail.go index ab2c377..c579304 100644 --- a/cmd/xwebmail/xwebmail.go +++ b/cmd/xwebmail/xwebmail.go @@ -12,22 +12,6 @@ import ( var addr = flag.String("addr", ":8080", "address:port to listen on") -type handler struct { - c *db.Conn -} - -func (h *handler) OriginalHandler(w http.ResponseWriter, r *http.Request) { - var blob []byte - hash := mux.Vars(r)["hash"] - if err := h.c.OriginalBlobByHash(hash, &blob); err != nil { - glog.Fatal(err) - } - w.Header().Set("Content-Type", "text/plain") - if _, err := w.Write(blob); err != nil { - glog.Error(err) - } -} - func main() { defer glog.Flush() flag.Parse() @@ -41,5 +25,6 @@ func main() { r := mux.NewRouter() r.HandleFunc("/raw/{hash}", h.OriginalHandler) + r.HandleFunc("/l/{label}", h.LabelHandler) glog.Fatal(http.ListenAndServe(*addr, r)) } diff --git a/db/util.go b/db/util.go index 465e3a6..6417620 100644 --- a/db/util.go +++ b/db/util.go @@ -223,3 +223,20 @@ VALUES } return nil } + +var MagicAllLabel = "[all]" + +type Paginator struct { + Label string + Offset int + Count int +} + +// Index returns ranges of metadata for messages as defined by paginator. +func (c *Conn) Index(p *Paginator) error { + if p.Label == MagicAllLabel { + // Paginate all messages. + } + // Else, filter by label. + return nil +} diff --git a/handlers/handlers.go b/handlers/handlers.go new file mode 100644 index 0000000..590f6d8 --- /dev/null +++ b/handlers/handlers.go @@ -0,0 +1,81 @@ +package handlers + +import ( + "database/sql" + "flag" + "net/http" + "path/filepath" + + "github.com/golang/glog" + "github.com/gorilla/mux" + + "xinu.tv/email/db" +) + +var staticDir = flag.String("static", "static", + "directory containing static web resources.") + +type handler struct { + c *db.Conn +} + +func (h *handler) OriginalHandler(w http.ResponseWriter, r *http.Request) { + var blob []byte + hash := mux.Vars(r)["hash"] + err := h.c.OriginalBlobByHash(hash, &blob) + switch err { + case nil: + w.Header().Set("Content-Type", "text/plain") + if _, err := w.Write(blob); err != nil { + glog.Error(err) + } + case sql.ErrNoRows: + http.NotFound(w, r) + default: + glog.Error(err) + } +} + +func decodeToken(token string, p *db.Paginator) error { + return nil +} + +func (h *handler) LabelHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + p := &db.Paginator{Label: vars["label"]} + if p.Label == "" { + p.Label = db.MagicAllLabel + } + token := vars["token"] + if err := decodeToken(token, p); err != nil { + glog.Error("LabelHandler: Failed to decode token %q: %v", token, err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + glog.Infoln("Listing:", p) + if err := h.c.Index(p); err != nil { + glog.Errorln("LabelHandler:", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func staticHandler(w http.ResponseWriter, r *http.Request) { + fs := http.FileServer(http.Dir(*staticDir)) + if r.URL.Path == "/" { + http.ServeFile(w, r, filepath.Join(*staticDir, "index.html")) + return + } + fs.ServeHTTP(w, r) +} + +func Handlers(c *db.Conn) http.Handler { + h := &handler{c: c} + + r := mux.NewRouter() + r.HandleFunc("/css/", staticHandler) + r.HandleFunc("/raw/{hash}", h.OriginalHandler) + r.HandleFunc("/l/{label}", h.LabelHandler) + r.PathPrefix("/").HandlerFunc(staticHandler) + return r +}