Rudimentary HTTP GUI
This commit is contained in:
106
gui.go
Normal file
106
gui.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"bitbucket.org/tebeka/nrsc"
|
||||
|
||||
"github.com/codegangsta/martini"
|
||||
)
|
||||
|
||||
func startGUI(addr string, m *Model) {
|
||||
router := martini.NewRouter()
|
||||
router.Get("/rest/version", restGetVersion)
|
||||
router.Get("/rest/model", restGetModel)
|
||||
router.Get("/rest/connections", restGetConnections)
|
||||
router.Get("/rest/config", restGetConfig)
|
||||
router.Get("/rest/need", restGetNeed)
|
||||
|
||||
go func() {
|
||||
mr := martini.New()
|
||||
mr.Use(nrscStatic("gui"))
|
||||
mr.Use(martini.Recovery())
|
||||
mr.Action(router.Handle)
|
||||
mr.Map(m)
|
||||
http.ListenAndServe(addr, mr)
|
||||
}()
|
||||
}
|
||||
|
||||
func restGetVersion() string {
|
||||
return Version
|
||||
}
|
||||
|
||||
func restGetModel(m *Model, w http.ResponseWriter) {
|
||||
var res = make(map[string]interface{})
|
||||
|
||||
res["globalFiles"], res["globalDeleted"], res["globalBytes"] = m.GlobalSize()
|
||||
res["localFiles"], res["localDeleted"], res["localBytes"] = m.LocalSize()
|
||||
files, total := m.NeedFiles()
|
||||
res["needFiles"], res["needBytes"] = len(files), total
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
func restGetConnections(m *Model, w http.ResponseWriter) {
|
||||
var res = m.ConnectionStats()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
func restGetConfig(w http.ResponseWriter) {
|
||||
var res = make(map[string]interface{})
|
||||
res["repository"] = config.OptionMap("repository")
|
||||
res["nodes"] = config.OptionMap("nodes")
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(res)
|
||||
}
|
||||
|
||||
func restGetNeed(m *Model, w http.ResponseWriter) {
|
||||
files, _ := m.NeedFiles()
|
||||
if files == nil {
|
||||
// We don't want the empty list to serialize as "null\n"
|
||||
files = make([]FileInfo, 0)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(files)
|
||||
}
|
||||
|
||||
func nrscStatic(path string) interface{} {
|
||||
if err := nrsc.Initialize(); err != nil {
|
||||
panic("Unable to initialize nrsc: " + err.Error())
|
||||
}
|
||||
return func(res http.ResponseWriter, req *http.Request, log *log.Logger) {
|
||||
file := req.URL.Path
|
||||
|
||||
// nrsc expects there not to be a leading slash
|
||||
if file[0] == '/' {
|
||||
file = file[1:]
|
||||
}
|
||||
|
||||
f := nrsc.Get(file)
|
||||
if f == nil {
|
||||
return
|
||||
}
|
||||
|
||||
rdr, err := f.Open()
|
||||
if err != nil {
|
||||
http.Error(res, "Internal Server Error", http.StatusInternalServerError)
|
||||
}
|
||||
defer rdr.Close()
|
||||
|
||||
mtype := mime.TypeByExtension(filepath.Ext(req.URL.Path))
|
||||
if len(mtype) != 0 {
|
||||
res.Header().Set("Content-Type", mtype)
|
||||
}
|
||||
res.Header().Set("Content-Size", fmt.Sprintf("%d", f.Size()))
|
||||
res.Header().Set("Last-Modified", f.ModTime().UTC().Format(http.TimeFormat))
|
||||
|
||||
io.Copy(res, rdr)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user