Browse Source

cmd/syncthing: Use ReadAll + json.Unmarshal in places were we care about consuming the reader

Because json.NewDecoder(r).Decode(&v) doesn't necessarily consume all
data on the reader, that means an HTTP connection can't be reused. We
don't do a lot of HTTP traffic where we read JSON responses, but the
discovery is one such place. The other two are for POSTs from the GUI,
where it's not exactly critical but still nice if the connection still
can be keep-alive'd after the request as well.

Also ensure that we call req.Body.Close() for clarity, even though this
should by all accounts not really be necessary.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3050
Jakob Borg 9 years ago
parent
commit
39899e40bf
3 changed files with 23 additions and 5 deletions
  1. 8 2
      cmd/syncthing/gui.go
  2. 7 1
      lib/config/config.go
  3. 8 2
      lib/discover/global.go

+ 8 - 2
cmd/syncthing/gui.go

@@ -718,6 +718,7 @@ func (s *apiService) postSystemConfig(w http.ResponseWriter, r *http.Request) {
 	defer s.systemConfigMut.Unlock()
 	defer s.systemConfigMut.Unlock()
 
 
 	to, err := config.ReadJSON(r.Body, myID)
 	to, err := config.ReadJSON(r.Body, myID)
+	r.Body.Close()
 	if err != nil {
 	if err != nil {
 		l.Warnln("decoding posted config:", err)
 		l.Warnln("decoding posted config:", err)
 		http.Error(w, err.Error(), http.StatusBadRequest)
 		http.Error(w, err.Error(), http.StatusBadRequest)
@@ -940,10 +941,15 @@ func (s *apiService) getDBIgnores(w http.ResponseWriter, r *http.Request) {
 func (s *apiService) postDBIgnores(w http.ResponseWriter, r *http.Request) {
 func (s *apiService) postDBIgnores(w http.ResponseWriter, r *http.Request) {
 	qs := r.URL.Query()
 	qs := r.URL.Query()
 
 
-	var data map[string][]string
-	err := json.NewDecoder(r.Body).Decode(&data)
+	bs, err := ioutil.ReadAll(r.Body)
 	r.Body.Close()
 	r.Body.Close()
+	if err != nil {
+		http.Error(w, err.Error(), 500)
+		return
+	}
 
 
+	var data map[string][]string
+	err = json.Unmarshal(bs, &data)
 	if err != nil {
 	if err != nil {
 		http.Error(w, err.Error(), 500)
 		http.Error(w, err.Error(), 500)
 		return
 		return

+ 7 - 1
lib/config/config.go

@@ -11,6 +11,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"encoding/xml"
 	"encoding/xml"
 	"io"
 	"io"
+	"io/ioutil"
 	"net/url"
 	"net/url"
 	"os"
 	"os"
 	"sort"
 	"sort"
@@ -92,7 +93,12 @@ func ReadJSON(r io.Reader, myID protocol.DeviceID) (Configuration, error) {
 	util.SetDefaults(&cfg.Options)
 	util.SetDefaults(&cfg.Options)
 	util.SetDefaults(&cfg.GUI)
 	util.SetDefaults(&cfg.GUI)
 
 
-	err := json.NewDecoder(r).Decode(&cfg)
+	bs, err := ioutil.ReadAll(r)
+	if err != nil {
+		return cfg, err
+	}
+
+	err = json.Unmarshal(bs, &cfg)
 	cfg.OriginalVersion = cfg.Version
 	cfg.OriginalVersion = cfg.Version
 
 
 	cfg.prepare(myID)
 	cfg.prepare(myID)

+ 8 - 2
lib/discover/global.go

@@ -12,6 +12,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"io"
 	"io"
+	"io/ioutil"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
 	"strconv"
 	"strconv"
@@ -154,9 +155,14 @@ func (c *globalClient) Lookup(device protocol.DeviceID) (addresses []string, err
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	var ann announcement
-	err = json.NewDecoder(resp.Body).Decode(&ann)
+	bs, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
 	resp.Body.Close()
 	resp.Body.Close()
+
+	var ann announcement
+	err = json.Unmarshal(bs, &ann)
 	return ann.Addresses, err
 	return ann.Addresses, err
 }
 }