faas/gateway/handlers/forwarding_proxy_test.go
Thomas E Lackey 7870b87c38 Implement proposal 716, passing full paths through the Gateway and fwatchdog.
Previously, only the query string of the URL was passed through the Gateway.
With this change, the entire path requested by the client is passed through as well as the query string.

While fwatchdog already supported passing the path through, in practice this would not happen
since the Gateway would have swallowed it before forwarding the request to the watchdog.

With this change, the path portion after the function name is added to the Http_Path environment
variable, provided that cgiHeaders are enabled.  This is similar to the of-watchdog equivalent.

Signed-off-by: Thomas E Lackey <telackey@bozemanpass.com>
2018-08-29 12:41:04 +01:00

197 lines
5.0 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()
}
upstream := buildUpstreamRequest(request, "http://xyz:8080", request.URL.Path)
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()
}
}