From 52266a6741e542be77d4fc2648fb0764d1692406 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 28 Jan 2017 12:26:30 +0000 Subject: [PATCH] Match content-type of incoming request. Fix for Alexa. --- docker-compose.yml | 14 ++++- gateway/build.sh | 2 +- gateway/handlers/proxy.go | 51 +++++-------------- gateway/server.go | 6 ++- sample-functions/ChangeColorIntent/Dockerfile | 3 +- sample-functions/ChangeColorIntent/blue.json | 29 +++++++++++ sample-functions/ChangeColorIntent/build.sh | 4 ++ sample-functions/ChangeColorIntent/green.json | 29 +++++++++++ sample-functions/ChangeColorIntent/handler.js | 6 +-- sample-functions/ChangeColorIntent/red.json | 29 +++++++++++ .../ChangeColorIntent/sample.json | 16 ------ .../ChangeColorIntent/sample_request.json | 29 +++++++++++ watchdog/main.go | 4 ++ 13 files changed, 161 insertions(+), 61 deletions(-) create mode 100644 sample-functions/ChangeColorIntent/blue.json create mode 100755 sample-functions/ChangeColorIntent/build.sh create mode 100644 sample-functions/ChangeColorIntent/green.json create mode 100644 sample-functions/ChangeColorIntent/red.json delete mode 100644 sample-functions/ChangeColorIntent/sample.json create mode 100644 sample-functions/ChangeColorIntent/sample_request.json diff --git a/docker-compose.yml b/docker-compose.yml index 8c41d872..e613213b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -72,7 +72,6 @@ services: environment: no_proxy: "gateway" https_proxy: $https_proxy - nodeinfo: image: alexellis2/faas-nodeinfo:latest depends_on: @@ -105,6 +104,19 @@ services: no_proxy: "gateway" https_proxy: $https_proxy + + # alexacolorchange: + # image: alexellis2/faas-alexachangecolorintent + # depends_on: + # - gateway + # networks: + # - functions + # environment: + # no_proxy: "gateway" + # https_proxy: $https_proxy + + + networks: functions: driver: overlay diff --git a/gateway/build.sh b/gateway/build.sh index 3f93f69e..8e34c779 100755 --- a/gateway/build.sh +++ b/gateway/build.sh @@ -10,4 +10,4 @@ docker rm -f gateway_extract echo Building alexellis2/faas-gateway:latest -docker build -t alexellis2/faas-gateway:latest-dev3 . +docker build -t alexellis2/faas-gateway:latest-dev4 . diff --git a/gateway/handlers/proxy.go b/gateway/handlers/proxy.go index eb2d5de5..dcf4de09 100644 --- a/gateway/handlers/proxy.go +++ b/gateway/handlers/proxy.go @@ -3,24 +3,21 @@ package handlers import ( "bytes" "context" - "encoding/json" "fmt" "io/ioutil" "net/http" "strconv" - "strings" "time" "github.com/Sirupsen/logrus" "github.com/alexellis/faas/gateway/metrics" - "github.com/alexellis/faas/gateway/requests" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" "github.com/gorilla/mux" ) -// makeProxy creates a proxy for HTTP web requests which can be routed to a function. +// 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 { return func(w http.ResponseWriter, r *http.Request) { metrics.GatewayRequestsTotal.Inc() @@ -40,45 +37,15 @@ func MakeProxy(metrics metrics.MetricOptions, wildcard bool, c *client.Client, l } else if len(header) > 0 { lookupInvoke(w, r, metrics, header[0], c, logger) defer r.Body.Close() - } else { - requestBody, _ := ioutil.ReadAll(r.Body) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Provide a named /function URL or an x-function header.")) defer r.Body.Close() - alexaService := IsAlexa(requestBody) - fmt.Println(alexaService) - defer r.Body.Close() - - if len(alexaService.Session.SessionId) > 0 && - len(alexaService.Session.Application.ApplicationId) > 0 && - len(alexaService.Request.Intent.Name) > 0 { - - fmt.Println("Alexa SDK request found") - fmt.Printf("SessionId=%s, Intent=%s, AppId=%s\n", alexaService.Session.SessionId, alexaService.Request.Intent.Name, alexaService.Session.Application.ApplicationId) - - invokeService(w, r, metrics, alexaService.Request.Intent.Name, requestBody, logger) - - } else { - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Provide an x-function header or a valid Alexa SDK request.")) - defer r.Body.Close() - } } } } } -func IsAlexa(requestBody []byte) requests.AlexaRequestBody { - body := requests.AlexaRequestBody{} - buf := bytes.NewBuffer(requestBody) - // fmt.Println(buf) - str := buf.String() - parts := strings.Split(str, "sessionId") - if len(parts) > 1 { - json.Unmarshal(requestBody, &body) - } - return body -} - func lookupInvoke(w http.ResponseWriter, r *http.Request, metrics metrics.MetricOptions, name string, c *client.Client, logger *logrus.Logger) { exists, err := lookupSwarmService(name, c) if err != nil || exists == false { @@ -112,9 +79,14 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri start := time.Now() buf := bytes.NewBuffer(requestBody) url := "http://" + service + ":" + strconv.Itoa(8080) + "/" - fmt.Printf("[%s] Forwarding request to: %s\n", stamp, url) + contentType := r.Header.Get("Content-Type") + if len(contentType) == 0 { + contentType = "text/plain" + } - response, err := http.Post(url, "text/plain", buf) + fmt.Printf("[%s] Forwarding request [%s] to: %s\n", stamp, contentType, url) + + response, err := http.Post(url, r.Header.Get("Content-Type"), buf) if err != nil { logger.Infoln(err) w.WriteHeader(500) @@ -132,6 +104,9 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri return } + // Match header for strict services + w.Header().Set("Content-Type", r.Header.Get("Content-Type")) + w.WriteHeader(http.StatusOK) w.Write(responseBody) diff --git a/gateway/server.go b/gateway/server.go index 2616410c..de6494c3 100644 --- a/gateway/server.go +++ b/gateway/server.go @@ -33,7 +33,11 @@ func main() { metrics.RegisterMetrics(metricsOptions) r := mux.NewRouter() - r.HandleFunc("/function/{name:[a-zA-Z_]+}", faashandlers.MakeProxy(metricsOptions, true, dockerClient, &logger)) + // r.StrictSlash(false) + + functionHandler := faashandlers.MakeProxy(metricsOptions, true, dockerClient, &logger) + r.HandleFunc("/function/{name:[a-zA-Z_]+}", functionHandler) + r.HandleFunc("/function/{name:[a-zA-Z_]+}/", functionHandler) r.HandleFunc("/system/alert", faashandlers.MakeAlertHandler(dockerClient)) r.HandleFunc("/system/functions", faashandlers.MakeFunctionReader(metricsOptions, dockerClient)).Methods("GET") diff --git a/sample-functions/ChangeColorIntent/Dockerfile b/sample-functions/ChangeColorIntent/Dockerfile index 5a083c07..3abd8cdb 100644 --- a/sample-functions/ChangeColorIntent/Dockerfile +++ b/sample-functions/ChangeColorIntent/Dockerfile @@ -1,7 +1,8 @@ FROM alpine:latest RUN apk --update add nodejs -ADD https://github.com/alexellis/faas/releases/download/v0.3-alpha/fwatchdog /usr/bin +#ADD https://github.com/alexellis/faas/releases/download/v0.3-alpha/fwatchdog /usr/bin +COPY ./fwatchdog /usr/bin/ RUN chmod +x /usr/bin/fwatchdog COPY package.json . diff --git a/sample-functions/ChangeColorIntent/blue.json b/sample-functions/ChangeColorIntent/blue.json new file mode 100644 index 00000000..4fbd39eb --- /dev/null +++ b/sample-functions/ChangeColorIntent/blue.json @@ -0,0 +1,29 @@ +{ + "session": { + "sessionId": "SessionId.3f589830-c369-45a3-9c8d-7f5271777dd8", + "application": { + "applicationId": "amzn1.ask.skill.b32fb0db-f0f0-4e64-b862-48e506f4ea68" + }, + "attributes": {}, + "user": { + "userId": "amzn1.ask.account.AEUHSFGVXWOYRSM2A7SVAK47L3I44TVOG6DBCTY2ACYSCUYQ65MWDZLUBZHLDD3XEMCYRLS4VSA54PQ7QBQW6FZLRJSMP5BOZE2B52YURUOSNOWORL44QGYDRXR3H7A7Y33OP3XKMUSJXIAFH7T2ZA6EQBLYRD34BPLTJXE3PDZE3V4YNFYUECXQNNH4TRG3ZBOYH2BF4BTKIIQ" + }, + "new": true + }, + "request": { + "type": "IntentRequest", + "requestId": "EdwRequestId.9ddf1ea0-c582-4dd0-8547-359f71639c1d", + "locale": "en-GB", + "timestamp": "2017-01-28T11:02:59Z", + "intent": { + "name": "ChangeColorIntent", + "slots": { + "LedColor": { + "name": "LedColor", + "value": "blue" + } + } + } + }, + "version": "1.0" +} diff --git a/sample-functions/ChangeColorIntent/build.sh b/sample-functions/ChangeColorIntent/build.sh new file mode 100755 index 00000000..79fbc49e --- /dev/null +++ b/sample-functions/ChangeColorIntent/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +docker build -t alexellis2/faas-alexachangecolorintent . + diff --git a/sample-functions/ChangeColorIntent/green.json b/sample-functions/ChangeColorIntent/green.json new file mode 100644 index 00000000..a43e3ec1 --- /dev/null +++ b/sample-functions/ChangeColorIntent/green.json @@ -0,0 +1,29 @@ +{ + "session": { + "sessionId": "SessionId.ce487e6e-9975-4c95-b305-2a0b354f3ee0", + "application": { + "applicationId": "amzn1.ask.skill.dc0c07b4-e18d-4f6f-a571-90cd1aca3bc6" + }, + "attributes": {}, + "user": { + "userId": "amzn1.ask.account.AEFGBTDIPL5K3HYKXGNAXDHANW2MPMFRRM5QX7FCMUEOJYCGNIVUTVR7IUUHZ2VFPIDNOPIUBWZLGYSSLOBLZ6FR5FRUJMP3OAZKUI3ZZ4ADLR7M4ROICY5H5RFASQLTV5IUNIOTA7OP6N2ZNCXXZDXS7BVGPB6GKIWZAJRHOGUYSBHX2JMSLNPQ6V6HMFKGKZLAWLHKGYEUDBI" + }, + "new": true + }, + "request": { + "type": "IntentRequest", + "requestId": "EdwRequestId.ee57cb67-a465-4d93-9ea8-29229f2634bc", + "locale": "en-GB", + "timestamp": "2017-01-28T11:32:04Z", + "intent": { + "name": "ChangeColorIntent", + "slots": { + "LedColor": { + "name": "LedColor", + "value": "green" + } + } + } + }, + "version": "1.0" +} diff --git a/sample-functions/ChangeColorIntent/handler.js b/sample-functions/ChangeColorIntent/handler.js index 1439055f..3a5d9ce1 100644 --- a/sample-functions/ChangeColorIntent/handler.js +++ b/sample-functions/ChangeColorIntent/handler.js @@ -2,10 +2,10 @@ let fs = require('fs'); let sample = require("./sample.json"); let SendColor = require('./sendColor'); -let sendColor = new SendColor("alexellis.io/tree1") +let sendColor = new SendColor("alexellis.io/officelights") const getStdin = require('get-stdin'); - + getStdin().then(content => { let request = JSON.parse(content); handle(request, request.request.intent); @@ -14,7 +14,7 @@ getStdin().then(content => { function tellWithCard(speechOutput) { sample.response.outputSpeech.text = speechOutput sample.response.card.content = speechOutput - sample.response.card.title = "Christmas Lights"; + sample.response.card.title = "Office Lights"; console.log(JSON.stringify(sample)); process.exit(0); } diff --git a/sample-functions/ChangeColorIntent/red.json b/sample-functions/ChangeColorIntent/red.json new file mode 100644 index 00000000..22db9332 --- /dev/null +++ b/sample-functions/ChangeColorIntent/red.json @@ -0,0 +1,29 @@ +{ + "session": { + "sessionId": "SessionId.3f589830-c369-45a3-9c8d-7f5271777dd8", + "application": { + "applicationId": "amzn1.ask.skill.b32fb0db-f0f0-4e64-b862-48e506f4ea68" + }, + "attributes": {}, + "user": { + "userId": "amzn1.ask.account.AEUHSFGVXWOYRSM2A7SVAK47L3I44TVOG6DBCTY2ACYSCUYQ65MWDZLUBZHLDD3XEMCYRLS4VSA54PQ7QBQW6FZLRJSMP5BOZE2B52YURUOSNOWORL44QGYDRXR3H7A7Y33OP3XKMUSJXIAFH7T2ZA6EQBLYRD34BPLTJXE3PDZE3V4YNFYUECXQNNH4TRG3ZBOYH2BF4BTKIIQ" + }, + "new": true + }, + "request": { + "type": "IntentRequest", + "requestId": "EdwRequestId.9ddf1ea0-c582-4dd0-8547-359f71639c1d", + "locale": "en-GB", + "timestamp": "2017-01-28T11:02:59Z", + "intent": { + "name": "ChangeColorIntent", + "slots": { + "LedColor": { + "name": "LedColor", + "value": "red" + } + } + } + }, + "version": "1.0" +} diff --git a/sample-functions/ChangeColorIntent/sample.json b/sample-functions/ChangeColorIntent/sample.json deleted file mode 100644 index 27fc86ca..00000000 --- a/sample-functions/ChangeColorIntent/sample.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "1.0", - "response": { - "outputSpeech": { - "type": "PlainText", - "text": "There's currently 6 people in space" - }, - "card": { - "content": "There's currently 6 people in space", - "title": "People in space", - "type": "Simple" - }, - "shouldEndSession": true - }, - "sessionAttributes": {} -} diff --git a/sample-functions/ChangeColorIntent/sample_request.json b/sample-functions/ChangeColorIntent/sample_request.json new file mode 100644 index 00000000..0b8270a7 --- /dev/null +++ b/sample-functions/ChangeColorIntent/sample_request.json @@ -0,0 +1,29 @@ +{ + "session": { + "sessionId": "SessionId.3f589830-c369-45a3-9c8d-7f5271777dd8", + "application": { + "applicationId": "amzn1.ask.skill.b32fb0db-f0f0-4e64-b862-48e506f4ea68" + }, + "attributes": {}, + "user": { + "userId": "amzn1.ask.account.AEUHSFGVXWOYRSM2A7SVAK47L3I44TVOG6DBCTY2ACYSCUYQ65MWDZLUBZHLDD3XEMCYRLS4VSA54PQ7QBQW6FZLRJSMP5BOZE2B52YURUOSNOWORL44QGYDRXR3H7A7Y33OP3XKMUSJXIAFH7T2ZA6EQBLYRD34BPLTJXE3PDZE3V4YNFYUECXQNNH4TRG3ZBOYH2BF4BTKIIQ" + }, + "new": true + }, + "request": { + "type": "IntentRequest", + "requestId": "EdwRequestId.9ddf1ea0-c582-4dd0-8547-359f71639c1d", + "locale": "en-GB", + "timestamp": "2017-01-28T11:02:59Z", + "intent": { + "name": "ChangeColorIntent", + "slots": { + "LedColor": { + "name": "LedColor", + "value": "blue" + } + } + } + }, + "version": "1.0" +} \ No newline at end of file diff --git a/watchdog/main.go b/watchdog/main.go index 35e0dd4a..a2c0598a 100644 --- a/watchdog/main.go +++ b/watchdog/main.go @@ -50,6 +50,10 @@ func makeRequestHandler(config *WatchdogConfig) func(http.ResponseWriter, *http. os.Stdout.Write(out) } + // Match header for strict services + if r.Header.Get("Content-Type") == "application/json" { + w.Header().Set("Content-Type", "application/json") + } w.WriteHeader(200) w.Write(out) } else {