mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 11:28:59 +00:00
Add helper function to format JSON responses
Every time a JSON object is returned in an HTTP response, the appropriate header needs to be set and the object itself needs to be encoded. Doing this in every function is repetitive and error prone (getDBFile and postDBScan, for instance, never set any headers). This adds a helper function to centralize the appropriate JSON response handling.
This commit is contained in:
parent
f208e6f0b6
commit
316be5ee34
@ -130,6 +130,11 @@ func (s *apiSvc) getListener(guiCfg config.GUIConfiguration) (net.Listener, erro
|
|||||||
return listener, nil
|
return listener, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendJSON(w http.ResponseWriter, jsonObject interface{}) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
json.NewEncoder(w).Encode(jsonObject)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *apiSvc) Serve() {
|
func (s *apiSvc) Serve() {
|
||||||
s.stop = make(chan struct{})
|
s.stop = make(chan struct{})
|
||||||
|
|
||||||
@ -366,15 +371,11 @@ func withDetailsMiddleware(id protocol.DeviceID, h http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) restPing(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) restPing(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, map[string]string{"ping": "pong"})
|
||||||
json.NewEncoder(w).Encode(map[string]string{
|
|
||||||
"ping": "pong",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, map[string]string{
|
||||||
json.NewEncoder(w).Encode(map[string]string{
|
|
||||||
"version": Version,
|
"version": Version,
|
||||||
"codename": Codename,
|
"codename": Codename,
|
||||||
"longVersion": LongVersion,
|
"longVersion": LongVersion,
|
||||||
@ -384,11 +385,10 @@ func (s *apiSvc) getSystemVersion(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemDebug(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemDebug(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
names := l.Facilities()
|
names := l.Facilities()
|
||||||
enabled := l.FacilityDebugging()
|
enabled := l.FacilityDebugging()
|
||||||
sort.Strings(enabled)
|
sort.Strings(enabled)
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
sendJSON(w, map[string]interface{}{
|
||||||
"facilities": names,
|
"facilities": names,
|
||||||
"enabled": enabled,
|
"enabled": enabled,
|
||||||
})
|
})
|
||||||
@ -424,11 +424,7 @@ func (s *apiSvc) getDBBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
levels = -1
|
levels = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, s.model.GlobalDirectoryTree(folder, prefix, levels, dirsonly))
|
||||||
|
|
||||||
tree := s.model.GlobalDirectoryTree(folder, prefix, levels, dirsonly)
|
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(tree)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -442,20 +438,15 @@ func (s *apiSvc) getDBCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
res := map[string]float64{
|
sendJSON(w, map[string]float64{
|
||||||
"completion": s.model.Completion(device, folder),
|
"completion": s.model.Completion(device, folder),
|
||||||
}
|
})
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
folder := qs.Get("folder")
|
folder := qs.Get("folder")
|
||||||
res := folderSummary(s.cfg, s.model, folder)
|
sendJSON(w, folderSummary(s.cfg, s.model, folder))
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func folderSummary(cfg *config.Wrapper, m *model.Model, folder string) map[string]interface{} {
|
func folderSummary(cfg *config.Wrapper, m *model.Model, folder string) map[string]interface{} {
|
||||||
@ -520,35 +511,26 @@ func (s *apiSvc) getDBNeed(w http.ResponseWriter, r *http.Request) {
|
|||||||
progress, queued, rest, total := s.model.NeedFolderFiles(folder, page, perpage)
|
progress, queued, rest, total := s.model.NeedFolderFiles(folder, page, perpage)
|
||||||
|
|
||||||
// Convert the struct to a more loose structure, and inject the size.
|
// Convert the struct to a more loose structure, and inject the size.
|
||||||
output := map[string]interface{}{
|
sendJSON(w, map[string]interface{}{
|
||||||
"progress": s.toNeedSlice(progress),
|
"progress": s.toNeedSlice(progress),
|
||||||
"queued": s.toNeedSlice(queued),
|
"queued": s.toNeedSlice(queued),
|
||||||
"rest": s.toNeedSlice(rest),
|
"rest": s.toNeedSlice(rest),
|
||||||
"total": total,
|
"total": total,
|
||||||
"page": page,
|
"page": page,
|
||||||
"perpage": perpage,
|
"perpage": perpage,
|
||||||
}
|
})
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(output)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemConnections(w http.ResponseWriter, r *http.Request) {
|
||||||
var res = s.model.ConnectionStats()
|
sendJSON(w, s.model.ConnectionStats())
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDeviceStats(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDeviceStats(w http.ResponseWriter, r *http.Request) {
|
||||||
var res = s.model.DeviceStatistics()
|
sendJSON(w, s.model.DeviceStatistics())
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getFolderStats(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getFolderStats(w http.ResponseWriter, r *http.Request) {
|
||||||
var res = s.model.FolderStatistics()
|
sendJSON(w, s.model.FolderStatistics())
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -559,7 +541,7 @@ func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
lf, _ := s.model.CurrentFolderFile(folder, file)
|
lf, _ := s.model.CurrentFolderFile(folder, file)
|
||||||
|
|
||||||
av := s.model.Availability(folder, file)
|
av := s.model.Availability(folder, file)
|
||||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
sendJSON(w, map[string]interface{}{
|
||||||
"global": jsonFileInfo(gf),
|
"global": jsonFileInfo(gf),
|
||||||
"local": jsonFileInfo(lf),
|
"local": jsonFileInfo(lf),
|
||||||
"availability": av,
|
"availability": av,
|
||||||
@ -567,8 +549,7 @@ func (s *apiSvc) getDBFile(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, s.cfg.Raw())
|
||||||
json.NewEncoder(w).Encode(s.cfg.Raw())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -615,8 +596,7 @@ func (s *apiSvc) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemConfigInsync(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, map[string]bool{"configInSync": configInSync})
|
||||||
json.NewEncoder(w).Encode(map[string]bool{"configInSync": configInSync})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemRestart(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) postSystemRestart(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -711,13 +691,11 @@ func (s *apiSvc) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
|||||||
res["uptime"] = int(time.Since(startTime).Seconds())
|
res["uptime"] = int(time.Since(startTime).Seconds())
|
||||||
res["startTime"] = startTime
|
res["startTime"] = startTime
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, res)
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemError(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemError(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, map[string][]logger.Line{
|
||||||
json.NewEncoder(w).Encode(map[string][]logger.Line{
|
|
||||||
"errors": s.guiErrors.Since(time.Time{}),
|
"errors": s.guiErrors.Since(time.Time{}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -736,9 +714,7 @@ func (s *apiSvc) getSystemLog(w http.ResponseWriter, r *http.Request) {
|
|||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
since, err := time.Parse(time.RFC3339, q.Get("since"))
|
||||||
l.Debugln(err)
|
l.Debugln(err)
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, map[string][]logger.Line{
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(map[string][]logger.Line{
|
|
||||||
"messages": s.systemLog.Since(since),
|
"messages": s.systemLog.Since(since),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -775,7 +751,6 @@ func (s *apiSvc) getSystemHTTPMetrics(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
devices := make(map[string]discover.CacheEntry)
|
devices := make(map[string]discover.CacheEntry)
|
||||||
|
|
||||||
if s.discoverer != nil {
|
if s.discoverer != nil {
|
||||||
@ -787,17 +762,15 @@ func (s *apiSvc) getSystemDiscovery(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(devices)
|
sendJSON(w, devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getReport(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getReport(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, reportData(s.cfg, s.model))
|
||||||
json.NewEncoder(w).Encode(reportData(s.cfg, s.model))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
ignores, patterns, err := s.model.GetIgnores(qs.Get("folder"))
|
ignores, patterns, err := s.model.GetIgnores(qs.Get("folder"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -805,7 +778,7 @@ func (s *apiSvc) getDBIgnores(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(map[string][]string{
|
sendJSON(w, map[string][]string{
|
||||||
"ignore": ignores,
|
"ignore": ignores,
|
||||||
"patterns": patterns,
|
"patterns": patterns,
|
||||||
})
|
})
|
||||||
@ -841,8 +814,6 @@ func (s *apiSvc) getEvents(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
s.fss.gotEventRequest()
|
s.fss.gotEventRequest()
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
// Flush before blocking, to indicate that we've received the request
|
// Flush before blocking, to indicate that we've received the request
|
||||||
// and that it should not be retried.
|
// and that it should not be retried.
|
||||||
f := w.(http.Flusher)
|
f := w.(http.Flusher)
|
||||||
@ -853,7 +824,7 @@ func (s *apiSvc) getEvents(w http.ResponseWriter, r *http.Request) {
|
|||||||
evs = evs[len(evs)-limit:]
|
evs = evs[len(evs)-limit:]
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(evs)
|
sendJSON(w, evs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -872,21 +843,20 @@ func (s *apiSvc) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
|||||||
res["newer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.Newer
|
res["newer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.Newer
|
||||||
res["majorNewer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.MajorNewer
|
res["majorNewer"] = upgrade.CompareVersions(rel.Tag, Version) == upgrade.MajorNewer
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, res)
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getDeviceID(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getDeviceID(w http.ResponseWriter, r *http.Request) {
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
idStr := qs.Get("id")
|
idStr := qs.Get("id")
|
||||||
id, err := protocol.DeviceIDFromString(idStr)
|
id, err := protocol.DeviceIDFromString(idStr)
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
json.NewEncoder(w).Encode(map[string]string{
|
sendJSON(w, map[string]string{
|
||||||
"id": id.String(),
|
"id": id.String(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
json.NewEncoder(w).Encode(map[string]string{
|
sendJSON(w, map[string]string{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -899,8 +869,7 @@ func (s *apiSvc) getLang(w http.ResponseWriter, r *http.Request) {
|
|||||||
parts := strings.SplitN(l, ";", 2)
|
parts := strings.SplitN(l, ";", 2)
|
||||||
langs = append(langs, strings.ToLower(strings.TrimSpace(parts[0])))
|
langs = append(langs, strings.ToLower(strings.TrimSpace(parts[0])))
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, langs)
|
||||||
json.NewEncoder(w).Encode(langs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) postSystemUpgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -971,7 +940,7 @@ func (s *apiSvc) postDBScan(w http.ResponseWriter, r *http.Request) {
|
|||||||
errors := s.model.ScanFolders()
|
errors := s.model.ScanFolders()
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
http.Error(w, "Error scanning folders", 500)
|
http.Error(w, "Error scanning folders", 500)
|
||||||
json.NewEncoder(w).Encode(errors)
|
sendJSON(w, errors)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1019,12 +988,10 @@ func (s *apiSvc) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
|||||||
comp[device] = int(tot[device] / count[device])
|
comp[device] = int(tot[device] / count[device])
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
sendJSON(w, comp)
|
||||||
json.NewEncoder(w).Encode(comp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *apiSvc) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
func (s *apiSvc) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
qs := r.URL.Query()
|
qs := r.URL.Query()
|
||||||
current := qs.Get("current")
|
current := qs.Get("current")
|
||||||
search, _ := osutil.ExpandTilde(current)
|
search, _ := osutil.ExpandTilde(current)
|
||||||
@ -1043,7 +1010,8 @@ func (s *apiSvc) getSystemBrowse(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(ret)
|
|
||||||
|
sendJSON(w, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
type embeddedStatic struct {
|
type embeddedStatic struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user