Add devweb support for auto-reloading webapp.

This commit is contained in:
Bill Thiede 2014-04-12 15:31:53 -07:00
parent 14bd95851c
commit 803913523e
4 changed files with 132 additions and 16 deletions

33
cmd/reloader/reloader.go Normal file
View File

@ -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()
}

View File

@ -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))
}

View File

@ -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
}

81
handlers/handlers.go Normal file
View File

@ -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
}