faas/gateway/handlers/forwarding_proxy_test.go
Alex Ellis (VMware) 2f98ca8802 Review changes for HTTP paths
This reviews the code and fixes up suggestions made by team for
the HTTP paths PR #789.

- Removed feature-flag (this is backwards-compatible, so I see
no value in adding the flag)
- There was a URL transform happening for calls proxied to the
back end, I changed this for the nil-transform - i.e. it does not
change anything in the URL
- Introduced variables to describe the regex indicies used in
the URL trimming.

Tested with Docker Swarm with a ruby-microservice, with
system calls and with function calls using the UI.

Signed-off-by: Alex Ellis (VMware) <alexellis2@gmail.com>
2018-08-29 12:41:04 +01:00

200 lines
5.1 KiB
Go

package handlers
import (
"bytes"
"io/ioutil"
"net/http"
"net/url"
"testing"
)
func Test_buildUpstreamRequest_Body_Method_Query(t *testing.T) {
srcBytes := []byte("hello world")
reader := bytes.NewReader(srcBytes)
request, _ := http.NewRequest(http.MethodPost, "/?code=1", reader)
request.Header.Set("X-Source", "unit-test")
if request.URL.RawQuery != "code=1" {
t.Errorf("Query - want: %s, got: %s", "code=1", request.URL.RawQuery)
t.Fail()
}
upstream := buildUpstreamRequest(request, "/", "")
if request.Method != upstream.Method {
t.Errorf("Method - want: %s, got: %s", request.Method, upstream.Method)
t.Fail()
}
upstreamBytes, _ := ioutil.ReadAll(upstream.Body)
if string(upstreamBytes) != string(srcBytes) {
t.Errorf("Body - want: %s, got: %s", string(upstreamBytes), string(srcBytes))
t.Fail()
}
if request.Header.Get("X-Source") != upstream.Header.Get("X-Source") {
t.Errorf("Header X-Source - want: %s, got: %s", request.Header.Get("X-Source"), upstream.Header.Get("X-Source"))
t.Fail()
}
if request.URL.RawQuery != upstream.URL.RawQuery {
t.Errorf("URL.RawQuery - want: %s, got: %s", request.URL.RawQuery, upstream.URL.RawQuery)
t.Fail()
}
}
func Test_buildUpstreamRequest_NoBody_GetMethod_NoQuery(t *testing.T) {
request, _ := http.NewRequest(http.MethodGet, "/", nil)
upstream := buildUpstreamRequest(request, "/", "")
if request.Method != upstream.Method {
t.Errorf("Method - want: %s, got: %s", request.Method, upstream.Method)
t.Fail()
}
if upstream.Body != nil {
t.Errorf("Body - expected nil")
t.Fail()
}
if request.URL.RawQuery != upstream.URL.RawQuery {
t.Errorf("URL.RawQuery - want: %s, got: %s", request.URL.RawQuery, upstream.URL.RawQuery)
t.Fail()
}
}
func Test_buildUpstreamRequest_HasHostHeaderWhenSet(t *testing.T) {
srcBytes := []byte("hello world")
reader := bytes.NewReader(srcBytes)
request, err := http.NewRequest(http.MethodPost, "http://gateway/function?code=1", reader)
if err != nil {
t.Fatal(err)
}
upstream := buildUpstreamRequest(request, "/", "/")
if request.Host != upstream.Host {
t.Errorf("Host - want: %s, got: %s", request.Host, upstream.Host)
}
}
func Test_buildUpstreamRequest_HostHeader_Empty_WhenNotSet(t *testing.T) {
srcBytes := []byte("hello world")
reader := bytes.NewReader(srcBytes)
request, err := http.NewRequest(http.MethodPost, "/function", reader)
if err != nil {
t.Fatal(err)
}
upstream := buildUpstreamRequest(request, "/", "/")
if request.Host != upstream.Host {
t.Errorf("Host - want: %s, got: %s", request.Host, upstream.Host)
}
}
func Test_getServiceName(t *testing.T) {
scenarios := []struct {
name string
url string
serviceName string
}{
{
name: "can handle request without trailing slash",
url: "/function/testFunc",
serviceName: "testFunc",
},
{
name: "can handle request with trailing slash",
url: "/function/testFunc/",
serviceName: "testFunc",
},
{
name: "can handle request with query parameters",
url: "/function/testFunc?name=foo",
serviceName: "testFunc",
},
{
name: "can handle request with trailing slash and query parameters",
url: "/function/testFunc/?name=foo",
serviceName: "testFunc",
},
{
name: "can handle request with a fragment",
url: "/function/testFunc#fragment",
serviceName: "testFunc",
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
u, err := url.Parse("http://openfaas.local" + s.url)
if err != nil {
t.Fatal(err)
}
service := getServiceName(u.Path)
if service != s.serviceName {
t.Fatalf("Incorrect service name - want: %s, got: %s", s.serviceName, service)
}
})
}
}
func Test_buildUpstreamRequest_Body_Method_Query_Path(t *testing.T) {
srcBytes := []byte("hello world")
path := "/my/deep/path"
reader := bytes.NewReader(srcBytes)
request, _ := http.NewRequest(http.MethodPost, "/function/xyz"+path+"?code=1", reader)
request.Header.Set("X-Source", "unit-test")
if request.URL.RawQuery != "code=1" {
t.Errorf("Query - want: %s, got: %s", "code=1", request.URL.RawQuery)
t.Fail()
}
transformer := FunctionPrefixTrimmingURLPathTransformer{}
transformedPath := transformer.Transform(request)
upstream := buildUpstreamRequest(request, "http://xyz:8080", transformedPath)
if request.Method != upstream.Method {
t.Errorf("Method - want: %s, got: %s", request.Method, upstream.Method)
t.Fail()
}
upstreamBytes, _ := ioutil.ReadAll(upstream.Body)
if string(upstreamBytes) != string(srcBytes) {
t.Errorf("Body - want: %s, got: %s", string(upstreamBytes), string(srcBytes))
t.Fail()
}
if request.Header.Get("X-Source") != upstream.Header.Get("X-Source") {
t.Errorf("Header X-Source - want: %s, got: %s", request.Header.Get("X-Source"), upstream.Header.Get("X-Source"))
t.Fail()
}
if request.URL.RawQuery != upstream.URL.RawQuery {
t.Errorf("URL.RawQuery - want: %s, got: %s", request.URL.RawQuery, upstream.URL.RawQuery)
t.Fail()
}
if path != upstream.URL.Path {
t.Errorf("URL.Path - want: %s, got: %s", path, upstream.URL.Path)
t.Fail()
}
}