api, gui: Prevent connection issues due to unsupported-upgrade (fixes #8569) (#8586)

There are some situations where an upgrade wouldn't be supported, even though the noUpgrade bool isn't set. So when handling the errors that are caused by this, when attempting an upgrade, it shouldn't lead to some sort of offline-message/restart/warning/etc...

I added some checks on specific errors related to this and return a 501 (Not Implemented) response instead, in case of an "UpgradeUnsupported"-error. Additionally, on the GUI-side, the 501-response is now not to be considered an error to act upon.
This commit is contained in:
Eric P
2022-10-06 21:27:08 +02:00
committed by GitHub
parent a0c80e030a
commit c791dba392
2 changed files with 30 additions and 22 deletions
@@ -183,8 +183,9 @@ angular.module('syncthing.core')
if (arg.status === 0) { if (arg.status === 0) {
// A network error, not an HTTP error // A network error, not an HTTP error
$scope.$emit(Events.OFFLINE); $scope.$emit(Events.OFFLINE);
} else if (arg.status >= 400 && arg.status <= 599) { } else if (arg.status >= 400 && arg.status <= 599 && arg.status != 501) {
// A genuine HTTP error // A genuine HTTP error. 501/NotImplemented is considered intentional
// and not an error which we need to act upon.
$('#networkError').modal('hide'); $('#networkError').modal('hide');
$('#restarting').modal('hide'); $('#restarting').modal('hide');
$('#shutdown').modal('hide'); $('#shutdown').modal('hide');
+27 -20
View File
@@ -864,7 +864,7 @@ func (s *service) getDBRemoteNeed(w http.ResponseWriter, r *http.Request) {
device := qs.Get("device") device := qs.Get("device")
deviceID, err := protocol.DeviceIDFromString(device) deviceID, err := protocol.DeviceIDFromString(device)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@@ -1017,7 +1017,7 @@ func (s *service) postSystemReset(w http.ResponseWriter, r *http.Request) {
if len(folder) > 0 { if len(folder) > 0 {
if _, ok := s.cfg.Folders()[folder]; !ok { if _, ok := s.cfg.Folders()[folder]; !ok {
http.Error(w, "Invalid folder ID", 500) http.Error(w, "Invalid folder ID", http.StatusInternalServerError)
return return
} }
} }
@@ -1291,7 +1291,7 @@ func (s *service) getReport(w http.ResponseWriter, r *http.Request) {
version = val version = val
} }
if r, err := s.urService.ReportDataPreview(context.TODO(), version); err != nil { if r, err := s.urService.ReportDataPreview(context.TODO(), version); err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} else { } else {
sendJSON(w, r) sendJSON(w, r)
@@ -1316,7 +1316,7 @@ func (s *service) getDBIgnores(w http.ResponseWriter, r *http.Request) {
lines, patterns, err := s.model.LoadIgnores(folder) lines, patterns, err := s.model.LoadIgnores(folder)
if err != nil && !ignore.IsParseError(err) { if err != nil && !ignore.IsParseError(err) {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@@ -1333,20 +1333,20 @@ func (s *service) postDBIgnores(w http.ResponseWriter, r *http.Request) {
bs, err := io.ReadAll(r.Body) bs, err := io.ReadAll(r.Body)
r.Body.Close() r.Body.Close()
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
var data map[string][]string var data map[string][]string
err = json.Unmarshal(bs, &data) err = json.Unmarshal(bs, &data)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
err = s.model.SetIgnores(qs.Get("folder"), data["ignore"]) err = s.model.SetIgnores(qs.Get("folder"), data["ignore"])
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@@ -1424,13 +1424,13 @@ func (s *service) getEventSub(mask events.EventType) events.BufferedSubscription
func (s *service) getSystemUpgrade(w http.ResponseWriter, _ *http.Request) { func (s *service) getSystemUpgrade(w http.ResponseWriter, _ *http.Request) {
if s.noUpgrade { if s.noUpgrade {
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), http.StatusServiceUnavailable) http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), http.StatusNotImplemented)
return return
} }
opts := s.cfg.Options() opts := s.cfg.Options()
rel, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases) rel, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) httpError(w, err)
return return
} }
res := make(map[string]interface{}) res := make(map[string]interface{})
@@ -1472,8 +1472,7 @@ func (s *service) postSystemUpgrade(w http.ResponseWriter, _ *http.Request) {
opts := s.cfg.Options() opts := s.cfg.Options()
rel, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases) rel, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
if err != nil { if err != nil {
l.Warnln("getting latest release:", err) httpError(w, err)
http.Error(w, err.Error(), 500)
return return
} }
@@ -1481,7 +1480,7 @@ func (s *service) postSystemUpgrade(w http.ResponseWriter, _ *http.Request) {
err = upgrade.To(rel) err = upgrade.To(rel)
if err != nil { if err != nil {
l.Warnln("upgrading:", err) l.Warnln("upgrading:", err)
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@@ -1528,7 +1527,7 @@ func (s *service) makeDevicePauseHandler(paused bool) http.HandlerFunc {
if msg != "" { if msg != "" {
http.Error(w, msg, status) http.Error(w, msg, status)
} else if err != nil { } else if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
} }
} }
} }
@@ -1540,7 +1539,7 @@ func (s *service) postDBScan(w http.ResponseWriter, r *http.Request) {
subs := qs["sub"] subs := qs["sub"]
err := s.model.ScanFolderSubdirs(folder, subs) err := s.model.ScanFolderSubdirs(folder, subs)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
nextStr := qs.Get("next") nextStr := qs.Get("next")
@@ -1551,7 +1550,7 @@ func (s *service) postDBScan(w http.ResponseWriter, r *http.Request) {
} else { } else {
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", http.StatusInternalServerError)
sendJSON(w, errors) sendJSON(w, errors)
return return
} }
@@ -1571,7 +1570,7 @@ func (*service) getQR(w http.ResponseWriter, r *http.Request) {
var text = qs.Get("text") var text = qs.Get("text")
code, err := qr.Encode(text, qr.M) code, err := qr.Encode(text, qr.M)
if err != nil { if err != nil {
http.Error(w, "Invalid", 500) http.Error(w, "Invalid", http.StatusInternalServerError)
return return
} }
@@ -1612,7 +1611,7 @@ func (s *service) getFolderVersions(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query() qs := r.URL.Query()
versions, err := s.model.GetFolderVersions(qs.Get("folder")) versions, err := s.model.GetFolderVersions(qs.Get("folder"))
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
sendJSON(w, versions) sendJSON(w, versions)
@@ -1624,20 +1623,20 @@ func (s *service) postFolderVersionsRestore(w http.ResponseWriter, r *http.Reque
bs, err := io.ReadAll(r.Body) bs, err := io.ReadAll(r.Body)
r.Body.Close() r.Body.Close()
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
var versions map[string]time.Time var versions map[string]time.Time
err = json.Unmarshal(bs, &versions) err = json.Unmarshal(bs, &versions)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
ferr, err := s.model.RestoreFolderVersions(qs.Get("folder"), versions) ferr, err := s.model.RestoreFolderVersions(qs.Get("folder"), versions)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
sendJSON(w, errorStringMap(ferr)) sendJSON(w, errorStringMap(ferr))
@@ -2015,3 +2014,11 @@ func isFolderNotFound(err error) bool {
} }
return false return false
} }
func httpError(w http.ResponseWriter, err error) {
if errors.Is(err, upgrade.ErrUpgradeUnsupported) {
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), http.StatusNotImplemented)
} else {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}