浏览代码

POST to /config should return an error when something bad happens (fixes #489)

Jakob Borg 11 年之前
父节点
当前提交
528cbf62ec
共有 2 个文件被更改,包括 99 次插入2 次删除
  1. 4 0
      cmd/syncthing/gui.go
  2. 95 2
      integration/http.go

+ 4 - 0
cmd/syncthing/gui.go

@@ -278,6 +278,8 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) {
 	err := json.NewDecoder(r.Body).Decode(&newCfg)
 	if err != nil {
 		l.Warnln(err)
+		http.Error(w, err.Error(), 500)
+		return
 	} else {
 		if newCfg.GUI.Password == "" {
 			// Leave it empty
@@ -287,6 +289,8 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) {
 			hash, err := bcrypt.GenerateFromPassword([]byte(newCfg.GUI.Password), 0)
 			if err != nil {
 				l.Warnln(err)
+				http.Error(w, err.Error(), 500)
+				return
 			} else {
 				newCfg.GUI.Password = string(hash)
 			}

+ 95 - 2
integration/http.go

@@ -8,6 +8,7 @@ package main
 
 import (
 	"bufio"
+	"bytes"
 	"flag"
 	"fmt"
 	"io/ioutil"
@@ -76,7 +77,9 @@ func main() {
 
 	if len(csrfToken) > 0 {
 		// If we have a CSRF token, verify that POST succeeds with it
-		tests = append(tests, testing.InternalTest{"TestPOSTWithCSRF", TestPOSTWithCSRF})
+		tests = append(tests, testing.InternalTest{"TestPostWitchCSRF", TestPostWitchCSRF})
+		tests = append(tests, testing.InternalTest{"TestGetPostConfigOK", TestGetPostConfigOK})
+		tests = append(tests, testing.InternalTest{"TestGetPostConfigFail", TestGetPostConfigFail})
 	}
 
 	fmt.Printf("Testing HTTP: CSRF=%v, API=%v, Auth=%v\n", len(csrfToken) > 0, len(apiKey) > 0, len(authUser) > 0)
@@ -184,7 +187,7 @@ func TestPOSTNoCSRF(t *testing.T) {
 	}
 }
 
-func TestPOSTWithCSRF(t *testing.T) {
+func TestPostWitchCSRF(t *testing.T) {
 	r, err := http.NewRequest("POST", "http://"+target+"/rest/error/clear", nil)
 	if err != nil {
 		t.Fatal(err)
@@ -204,6 +207,96 @@ func TestPOSTWithCSRF(t *testing.T) {
 	}
 }
 
+func TestGetPostConfigOK(t *testing.T) {
+	// Get config
+	r, err := http.NewRequest("GET", "http://"+target+"/rest/config", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(csrfToken) > 0 {
+		r.Header.Set("X-CSRF-Token", csrfToken)
+	}
+	if len(authUser) > 0 {
+		r.SetBasicAuth(authUser, authPass)
+	}
+	res, err := http.DefaultClient.Do(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Fatalf("Status %d != 200 for POST", res.StatusCode)
+	}
+	bs, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+
+	// Post same config back
+	r, err = http.NewRequest("POST", "http://"+target+"/rest/config", bytes.NewBuffer(bs))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(csrfToken) > 0 {
+		r.Header.Set("X-CSRF-Token", csrfToken)
+	}
+	if len(authUser) > 0 {
+		r.SetBasicAuth(authUser, authPass)
+	}
+	res, err = http.DefaultClient.Do(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Fatalf("Status %d != 200 for POST", res.StatusCode)
+	}
+}
+
+func TestGetPostConfigFail(t *testing.T) {
+	// Get config
+	r, err := http.NewRequest("GET", "http://"+target+"/rest/config", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(csrfToken) > 0 {
+		r.Header.Set("X-CSRF-Token", csrfToken)
+	}
+	if len(authUser) > 0 {
+		r.SetBasicAuth(authUser, authPass)
+	}
+	res, err := http.DefaultClient.Do(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 200 {
+		t.Fatalf("Status %d != 200 for POST", res.StatusCode)
+	}
+	bs, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+
+	// Post same config back, with some characters missing to create a syntax error
+	r, err = http.NewRequest("POST", "http://"+target+"/rest/config", bytes.NewBuffer(bs[2:]))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(csrfToken) > 0 {
+		r.Header.Set("X-CSRF-Token", csrfToken)
+	}
+	if len(authUser) > 0 {
+		r.SetBasicAuth(authUser, authPass)
+	}
+	res, err = http.DefaultClient.Do(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if res.StatusCode != 500 {
+		t.Fatalf("Status %d != 500 for POST", res.StatusCode)
+	}
+}
+
 func TestJSONEndpointsNoAuth(t *testing.T) {
 	for _, p := range jsonEndpoints {
 		r, err := http.NewRequest("GET", "http://"+target+p, nil)