Repository: inbucket/inbucket (go)

Issue:
[Rest Client] baseURL - unable to use a starting url
Currently only a hostname works with the "baseURL". If I put inbucket behind and api-server or proxy, and give it a path like:
```
https://my-api-server.example.com/inbucket
```

Then when I try and set this as the baseUrl, `https://my-api-server.example.com/api/v1` is used for rest requests instead of `https://my-api-server.example.com/inbucket/api/v1`

Pull request description:
[Rest Client] changing to enable relative urls
resolves #476 
I have done this globally, but potentially it could be better to have an option when creating the rest client to decide. But when creating the client, we base the "base" url, which to me means it can be more than schema and hostname.

Let me know what you think!

Patch:
diff --git a/pkg/rest/client/rest.go b/pkg/rest/client/rest.go
index d235ae0..623f089 100644
--- a/pkg/rest/client/rest.go
+++ b/pkg/rest/client/rest.go
@@ -22,11 +22,7 @@ type restClient struct {
 
 // do performs an HTTP request with this client and returns the response.
 func (c *restClient) do(method, uri string, body []byte) (*http.Response, error) {
-	rel, err := url.Parse(uri)
-	if err != nil {
-		return nil, err
-	}
-	url := c.baseURL.ResolveReference(rel)
+	url := c.baseURL.JoinPath(uri)
 	var r io.Reader
 	if body != nil {
 		r = bytes.NewReader(body)


Test patch:
diff --git a/pkg/rest/client/rest_test.go b/pkg/rest/client/rest_test.go
index 175dbc6..563e57f 100644
--- a/pkg/rest/client/rest_test.go
+++ b/pkg/rest/client/rest_test.go
@@ -2,6 +2,7 @@ package client
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"net/http"
 	"net/url"
@@ -9,15 +10,22 @@ import (
 )
 
 const baseURLStr = "http://test.local:8080"
+const baseURLPathStr = "http://test.local:8080/inbucket"
 
 var baseURL *url.URL
 
+var baseURLPath *url.URL
+
 func init() {
 	var err error
 	baseURL, err = url.Parse(baseURLStr)
 	if err != nil {
 		panic(err)
 	}
+	baseURLPath, err = url.Parse(baseURLPathStr)
+	if err != nil {
+		panic(err)
+	}
 }
 
 type mockHTTPClient struct {
@@ -51,32 +59,39 @@ func (m *mockHTTPClient) ReqBody() []byte {
 	return body
 }
 
-func TestDo(t *testing.T) {
-	var want, got string
-	mth := &mockHTTPClient{}
-	c := &restClient{mth, baseURL}
-	body := []byte("Test body")
-
-	_, err := c.do("POST", "/dopost", body)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	want = "POST"
-	got = mth.req.Method
-	if got != want {
-		t.Errorf("req.Method == %q, want %q", got, want)
-	}
-
-	want = baseURLStr + "/dopost"
-	got = mth.req.URL.String()
-	if got != want {
-		t.Errorf("req.URL == %q, want %q", got, want)
-	}
-
-	b := mth.ReqBody()
-	if !bytes.Equal(b, body) {
-		t.Errorf("req.Body == %q, want %q", b, body)
+func TestDoTable(t *testing.T) {
+	tests := []struct {
+		method     string
+		uri        string
+		wantMethod string
+		base       *url.URL
+		wantUrl    string
+		wantBody   []byte
+	}{
+		{method: "GET", wantMethod: "GET", uri: "/doget", base: baseURL, wantUrl: baseURLStr + "/doget", wantBody: []byte("Test body 1")},
+		{method: "POST", wantMethod: "POST", uri: "/dopost", base: baseURL, wantUrl: baseURLStr + "/dopost", wantBody: []byte("Test body 2")},
+		{method: "GET", wantMethod: "GET", uri: "/doget", base: baseURLPath, wantUrl: baseURLPathStr + "/doget", wantBody: []byte("Test body 3")},
+		{method: "POST", wantMethod: "POST", uri: "/dopost", base: baseURLPath, wantUrl: baseURLPathStr + "/dopost", wantBody: []byte("Test body 4")},
+	}
+	for _, test := range tests {
+		testname := fmt.Sprintf("%s,%s", test.method, test.wantUrl)
+		t.Run(testname, func(t *testing.T) {
+			mth := &mockHTTPClient{}
+			c := &restClient{mth, test.base}
+			_, err := c.do(test.method, test.uri, test.wantBody)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if mth.req.Method != test.wantMethod {
+				t.Errorf("req.Method == %q, want %q", mth.req.Method, test.wantMethod)
+			}
+			if mth.req.URL.String() != test.wantUrl {
+				t.Errorf("req.URL == %q, want %q", mth.req.URL.String(), test.wantUrl)
+			}
+			if !bytes.Equal(mth.ReqBody(), test.wantBody) {
+				t.Errorf("req.Body == %q, want %q", mth.ReqBody(), test.wantBody)
+			}
+		})
 	}
 }