syncthing/gui.go

159 lines
3.7 KiB
Go
Raw Normal View History

2014-01-05 22:54:57 +00:00
package main
import (
"encoding/json"
"fmt"
"log"
"mime"
"net/http"
"path/filepath"
2014-01-09 23:09:27 +00:00
"runtime"
"sync"
"time"
2014-01-05 22:54:57 +00:00
"github.com/calmh/syncthing/auto"
"github.com/calmh/syncthing/model"
2014-01-05 22:54:57 +00:00
"github.com/codegangsta/martini"
"github.com/cratonica/embed"
2014-01-05 22:54:57 +00:00
)
func startGUI(addr string, m *model.Model) {
2014-01-05 22:54:57 +00:00
router := martini.NewRouter()
2014-01-05 23:05:07 +00:00
router.Get("/", getRoot)
2014-01-05 22:54:57 +00:00
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)
2014-01-09 23:09:27 +00:00
router.Get("/rest/system", restGetSystem)
2014-01-05 22:54:57 +00:00
fs, err := embed.Unpack(auto.Resources)
if err != nil {
panic(err)
}
2014-01-05 22:54:57 +00:00
go func() {
mr := martini.New()
2014-01-20 22:08:29 +00:00
mr.Use(embeddedStatic(fs))
2014-01-05 22:54:57 +00:00
mr.Use(martini.Recovery())
mr.Action(router.Handle)
mr.Map(m)
err := http.ListenAndServe(addr, mr)
if err != nil {
warnln("GUI not possible:", err)
}
2014-01-05 22:54:57 +00:00
}()
2014-01-09 23:09:27 +00:00
2014-01-05 22:54:57 +00:00
}
2014-01-05 23:05:07 +00:00
func getRoot(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/index.html", 302)
}
2014-01-05 22:54:57 +00:00
func restGetVersion() string {
return Version
}
func restGetModel(m *model.Model, w http.ResponseWriter) {
2014-01-05 22:54:57 +00:00
var res = make(map[string]interface{})
2014-01-06 04:57:41 +00:00
globalFiles, globalDeleted, globalBytes := m.GlobalSize()
res["globalFiles"], res["globalDeleted"], res["globalBytes"] = globalFiles, globalDeleted, globalBytes
localFiles, localDeleted, localBytes := m.LocalSize()
res["localFiles"], res["localDeleted"], res["localBytes"] = localFiles, localDeleted, localBytes
2014-01-06 05:38:01 +00:00
inSyncFiles, inSyncBytes := m.InSyncSize()
res["inSyncFiles"], res["inSyncBytes"] = inSyncFiles, inSyncBytes
2014-01-05 22:54:57 +00:00
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.Model, w http.ResponseWriter) {
2014-01-05 22:54:57 +00:00
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{})
2014-01-12 22:19:03 +00:00
res["myID"] = myID
2014-01-05 22:54:57 +00:00
res["repository"] = config.OptionMap("repository")
res["nodes"] = config.OptionMap("nodes")
res["nodes"].(map[string]string)[myID] = "self"
2014-01-05 22:54:57 +00:00
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(res)
}
type guiFile model.File
func (f guiFile) MarshalJSON() ([]byte, error) {
type t struct {
Name string
Size int
}
return json.Marshal(t{
Name: f.Name,
Size: model.File(f).Size(),
})
}
func restGetNeed(m *model.Model, w http.ResponseWriter) {
2014-01-05 22:54:57 +00:00
files, _ := m.NeedFiles()
gfs := make([]guiFile, len(files))
for i, f := range files {
gfs[i] = guiFile(f)
2014-01-05 22:54:57 +00:00
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(gfs)
2014-01-05 22:54:57 +00:00
}
2014-01-09 23:09:27 +00:00
var cpuUsagePercent float64
var cpuUsageLock sync.RWMutex
func restGetSystem(w http.ResponseWriter) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
res := make(map[string]interface{})
res["goroutines"] = runtime.NumGoroutine()
res["alloc"] = m.Alloc
res["sys"] = m.Sys
cpuUsageLock.RLock()
res["cpuPercent"] = cpuUsagePercent
cpuUsageLock.RUnlock()
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(res)
}
2014-01-20 22:08:29 +00:00
func embeddedStatic(fs map[string][]byte) interface{} {
var modt = time.Now().UTC().Format(http.TimeFormat)
2014-01-05 22:54:57 +00:00
return func(res http.ResponseWriter, req *http.Request, log *log.Logger) {
file := req.URL.Path
if file[0] == '/' {
file = file[1:]
}
bs, ok := fs[file]
if !ok {
2014-01-05 22:54:57 +00:00
return
}
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", len(bs)))
res.Header().Set("Last-Modified", modt)
2014-01-05 22:54:57 +00:00
res.Write(bs)
2014-01-05 22:54:57 +00:00
}
}