all: Implement suture v4-api (#6947)

This commit is contained in:
Simon Frei
2020-11-17 13:19:04 +01:00
committed by GitHub
parent e8fc465ea8
commit 9524b51708
65 changed files with 617 additions and 693 deletions
+40 -40
View File
@@ -9,6 +9,7 @@ package api
import (
"bytes"
"compress/gzip"
"context"
"encoding/json"
"fmt"
"io"
@@ -34,7 +35,8 @@ import (
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil"
"github.com/syncthing/syncthing/lib/ur"
"github.com/thejerf/suture"
"github.com/syncthing/syncthing/lib/util"
"github.com/thejerf/suture/v4"
)
var (
@@ -113,15 +115,14 @@ func TestStopAfterBrokenConfig(t *testing.T) {
}
w := config.Wrap("/dev/null", cfg, events.NoopLogger)
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, false).(*service)
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
defer os.Remove(token)
srv.started = make(chan string)
sup := suture.New("test", suture.Spec{
PassThroughPanics: true,
})
sup := suture.New("test", util.Spec())
sup.Add(srv)
sup.ServeBackground()
ctx, cancel := context.WithCancel(context.Background())
sup.ServeBackground(ctx)
<-srv.started
@@ -139,9 +140,7 @@ func TestStopAfterBrokenConfig(t *testing.T) {
t.Fatal("Verify config should have failed")
}
// Nonetheless, it should be fine to Stop() it without panic.
sup.Stop()
cancel()
}
func TestAssetsDir(t *testing.T) {
@@ -250,11 +249,11 @@ func TestAPIServiceRequests(t *testing.T) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
cases := []httpTestCase{
// /rest/db
@@ -519,11 +518,11 @@ func TestHTTPLogin(t *testing.T) {
cfg := new(mockedConfig)
cfg.gui.User = "üser"
cfg.gui.Password = "$2a$10$IdIZTxTg/dCNuNEGlmLynOjqg4B1FvDKuIV5e0BB3pnWVHNb8.GSq" // bcrypt of "räksmörgås" in UTF-8
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
// Verify rejection when not using authorization
@@ -581,7 +580,7 @@ func TestHTTPLogin(t *testing.T) {
}
}
func startHTTP(cfg config.Wrapper) (string, *suture.Supervisor, error) {
func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) {
m := new(mockedModel)
assetDir := "../../gui"
eventSub := new(mockedEventSub)
@@ -594,7 +593,7 @@ func startHTTP(cfg config.Wrapper) (string, *suture.Supervisor, error) {
// Instantiate the API service
urService := ur.New(cfg, m, connections, false)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, &mockedFolderSummaryService{}, errorLog, systemLog, nil, false).(*service)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, &mockedFolderSummaryService{}, errorLog, systemLog, false).(*service)
defer os.Remove(token)
svc.started = addrChan
@@ -603,14 +602,15 @@ func startHTTP(cfg config.Wrapper) (string, *suture.Supervisor, error) {
PassThroughPanics: true,
})
supervisor.Add(svc)
supervisor.ServeBackground()
ctx, cancel := context.WithCancel(context.Background())
supervisor.ServeBackground(ctx)
// Make sure the API service is listening, and get the URL to use.
addr := <-addrChan
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
supervisor.Stop()
return "", nil, fmt.Errorf("weird address from API service: %w", err)
cancel()
return "", cancel, fmt.Errorf("weird address from API service: %w", err)
}
host, _, _ := net.SplitHostPort(cfg.GUI().RawAddress)
@@ -619,7 +619,7 @@ func startHTTP(cfg config.Wrapper) (string, *suture.Supervisor, error) {
}
baseURL := fmt.Sprintf("http://%s", net.JoinHostPort(host, strconv.Itoa(tcpAddr.Port)))
return baseURL, supervisor, nil
return baseURL, cancel, nil
}
func TestCSRFRequired(t *testing.T) {
@@ -628,11 +628,11 @@ func TestCSRFRequired(t *testing.T) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal("Unexpected error from getting base URL:", err)
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Minute,
@@ -704,11 +704,11 @@ func TestRandomString(t *testing.T) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Second,
}
@@ -797,11 +797,11 @@ func testConfigPost(data io.Reader) (*http.Response, error) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
return nil, err
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Second,
}
@@ -818,11 +818,11 @@ func TestHostCheck(t *testing.T) {
cfg := new(mockedConfig)
cfg.gui.RawAddress = "127.0.0.1:0"
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
// A normal HTTP get to the localhost-bound service should succeed
@@ -879,11 +879,11 @@ func TestHostCheck(t *testing.T) {
cfg = new(mockedConfig)
cfg.gui.RawAddress = "127.0.0.1:0"
cfg.gui.InsecureSkipHostCheck = true
baseURL, sup, err = startHTTP(cfg)
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
// A request with a suspicious Host header should be allowed
@@ -903,11 +903,11 @@ func TestHostCheck(t *testing.T) {
cfg = new(mockedConfig)
cfg.gui.RawAddress = "0.0.0.0:0"
cfg.gui.InsecureSkipHostCheck = true
baseURL, sup, err = startHTTP(cfg)
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
// A request with a suspicious Host header should be allowed
@@ -931,11 +931,11 @@ func TestHostCheck(t *testing.T) {
cfg = new(mockedConfig)
cfg.gui.RawAddress = "[::1]:0"
baseURL, sup, err = startHTTP(cfg)
baseURL, cancel, err = startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
// A normal HTTP get to the localhost-bound service should succeed
@@ -1026,11 +1026,11 @@ func TestAccessControlAllowOriginHeader(t *testing.T) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Second,
}
@@ -1057,11 +1057,11 @@ func TestOptionsRequest(t *testing.T) {
const testAPIKey = "foobarbaz"
cfg := new(mockedConfig)
cfg.gui.APIKey = testAPIKey
baseURL, sup, err := startHTTP(cfg)
baseURL, cancel, err := startHTTP(cfg)
if err != nil {
t.Fatal(err)
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Second,
}
@@ -1093,7 +1093,7 @@ func TestEventMasks(t *testing.T) {
cfg := new(mockedConfig)
defSub := new(mockedEventSub)
diskSub := new(mockedEventSub)
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, false).(*service)
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
defer os.Remove(token)
if mask := svc.getEventMask(""); mask != DefaultEventMask {
@@ -1253,11 +1253,11 @@ func TestConfigChanges(t *testing.T) {
defer os.Remove(tmpFile.Name())
w := config.Wrap(tmpFile.Name(), cfg, events.NoopLogger)
tmpFile.Close()
baseURL, sup, err := startHTTP(w)
baseURL, cancel, err := startHTTP(w)
if err != nil {
t.Fatal("Unexpected error from getting base URL:", err)
}
defer sup.Stop()
defer cancel()
cli := &http.Client{
Timeout: time.Second,