From 3aec97441ee91c66901b2e173e423e0103f237f4 Mon Sep 17 00:00:00 2001 From: Alex Ellis Date: Wed, 5 Apr 2017 22:34:45 +0100 Subject: [PATCH] Cleanup logging, give not allowed to GET on gateway functions --- gateway/handlers/proxy.go | 69 +++++++++++++----------- gateway/server.go | 1 + gateway/tests/integration/routes_test.go | 22 ++++---- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/gateway/handlers/proxy.go b/gateway/handlers/proxy.go index ed3e04a4..13b2eda8 100644 --- a/gateway/handlers/proxy.go +++ b/gateway/handlers/proxy.go @@ -23,7 +23,7 @@ import ( ) // MakeProxy creates a proxy for HTTP web requests which can be routed to a function. -func MakeProxy(metrics metrics.MetricOptions, wildcard bool, c *client.Client, logger *logrus.Logger) http.HandlerFunc { +func MakeProxy(metrics metrics.MetricOptions, wildcard bool, client *client.Client, logger *logrus.Logger) http.HandlerFunc { proxyClient := http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, @@ -39,27 +39,35 @@ func MakeProxy(metrics metrics.MetricOptions, wildcard bool, c *client.Client, l } return func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() if r.Method == "POST" { logger.Infoln(r.Header) - header := r.Header["X-Function"] - logger.Infoln(header) - if wildcard == true { + xfunctionHeader := r.Header["X-Function"] + if len(xfunctionHeader) > 0 { + logger.Infoln(xfunctionHeader) + } + + // getServiceName + var serviceName string + if wildcard { vars := mux.Vars(r) name := vars["name"] - fmt.Println("invoke by name") - lookupInvoke(w, r, metrics, name, c, logger, &proxyClient) - defer r.Body.Close() + serviceName = name + } else if len(xfunctionHeader) > 0 { + serviceName = xfunctionHeader[0] + } - } else if len(header) > 0 { - lookupInvoke(w, r, metrics, header[0], c, logger, &proxyClient) - defer r.Body.Close() + if len(serviceName) > 0 { + lookupInvoke(w, r, metrics, serviceName, client, logger, &proxyClient) } else { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Provide a named /function URL or an x-function header.")) - defer r.Body.Close() + w.Write([]byte("Provide an x-function header or valid route /function/function_name.")) } + + } else { + w.WriteHeader(http.StatusMethodNotAllowed) } } } @@ -82,12 +90,12 @@ func lookupInvoke(w http.ResponseWriter, r *http.Request, metrics metrics.Metric if err != nil || exists == false { if err != nil { - logger.Fatalln(err) + logger.Infof("Could not resolve service: %s error: %s.", name, err) } - writeHead(name, metrics, http.StatusInternalServerError, w) - w.Write([]byte("Error resolving service.")) - defer r.Body.Close() - return + + // TODO: Should record the 404/not found error in Prometheus. + writeHead(name, metrics, http.StatusNotFound, w) + w.Write([]byte(fmt.Sprintf("Cannot find service: %s.", name))) } if exists { @@ -106,19 +114,6 @@ func lookupSwarmService(serviceName string, c *client.Client) (bool, error) { return len(services) > 0, err } -func copyHeaders(destination *http.Header, source *http.Header) { - for k, vv := range *source { - vvClone := make([]string, len(vv)) - copy(vvClone, vv) - (*destination)[k] = vvClone - } -} - -func randomInt(min, max int) int { - rand.Seed(time.Now().Unix()) - return rand.Intn(max-min) + min -} - func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.MetricOptions, service string, requestBody []byte, logger *logrus.Logger, proxyClient *http.Client) { stamp := strconv.FormatInt(time.Now().Unix(), 10) @@ -129,6 +124,7 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri metrics.GatewayFunctionsHistogram.WithLabelValues(service).Observe(seconds) }(time.Now()) + //TODO: inject setting rather than looking up each time. var dnsrr bool if os.Getenv("dnsrr") == "true" { dnsrr = true @@ -185,3 +181,16 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri writeHead(service, metrics, http.StatusOK, w) w.Write(responseBody) } + +func copyHeaders(destination *http.Header, source *http.Header) { + for k, vv := range *source { + vvClone := make([]string, len(vv)) + copy(vvClone, vv) + (*destination)[k] = vvClone + } +} + +func randomInt(min, max int) int { + rand.Seed(time.Now().Unix()) + return rand.Intn(max-min) + min +} diff --git a/gateway/server.go b/gateway/server.go index d43b4f51..25d88190 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -10,6 +10,7 @@ import ( faasHandlers "github.com/alexellis/faas/gateway/handlers" "github.com/alexellis/faas/gateway/metrics" "github.com/docker/docker/client" + "github.com/gorilla/mux" ) diff --git a/gateway/tests/integration/routes_test.go b/gateway/tests/integration/routes_test.go index 72524d00..6e813cac 100644 --- a/gateway/tests/integration/routes_test.go +++ b/gateway/tests/integration/routes_test.go @@ -44,19 +44,19 @@ func fireRequestWithHeaders(url string, method string, reqBody string, headers m return string(body), res.StatusCode, readErr } -// TODO: Review this - should give StatusMethodNotAllowed, gives 200 OK func TestGet_Rejected(t *testing.T) { - // var reqBody string - // _, code, err := fireRequest("http://localhost:8080/function/func_echoit", http.MethodGet, reqBody) + var reqBody string + _, code, err := fireRequest("http://localhost:8080/function/func_echoit", http.MethodGet, reqBody) + want := http.StatusMethodNotAllowed + if code != want { + t.Logf("Failed got: %d, wanted: %d", code, want) + t.Fail() + } - // if code != http.StatusMethodNotAllowed { - // t.Logf("Failed got: %d", code) - // } - - // if err != nil { - // t.Log(err) - // t.Fail() - // } + if err != nil { + t.Log(err) + t.Fail() + } } func TestEchoIt_Post_Route_Handler_ForwardsClientHeaders(t *testing.T) {