Skip to content
Snippets Groups Projects
Commit 84d1c0ea authored by Alex's avatar Alex
Browse files

Enable routing via /functions/ endpoint

parent f2fdfde4
No related branches found
No related tags found
No related merge requests found
......@@ -19,9 +19,9 @@ This container acts in a similar way to the API Gateway on AWS. Requests can be
There are three options for routing:
* Routing is enabled through a `X-Function` header which matches a service name (function) directly.
* Functions created on the overlay network can be invoked by: http://localhost:8080/function/{servicename}
* Routing automatically detects Alexa SDK requests and forwards to a service name (function) that matches the Intent name
* [todo] individual routes can be set up mapping to a specific service name (function).
* Routing is enabled through a `X-Function` header which matches a service name (function) directly.
Features:
......
#!/bin/sh
echo Building catservice:latest
docker build -t catservice .
echo Building server:latest
docker build -t server .
......@@ -51,6 +51,7 @@ func lookupSwarmService(serviceName string) (bool, error) {
if err != nil {
log.Fatal("Error with Docker client.")
}
fmt.Printf("Resolving: '%s'\n", serviceName)
serviceFilter := filters.NewArgs()
serviceFilter.Add("name", serviceName)
services, err := c.ServiceList(context.Background(), types.ServiceListOptions{Filters: serviceFilter})
......@@ -95,6 +96,7 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri
return
}
w.WriteHeader(http.StatusOK)
w.Write(responseBody)
seconds := time.Since(start).Seconds()
fmt.Printf("[%s] took %f seconds\n", stamp, seconds)
......@@ -102,7 +104,22 @@ func invokeService(w http.ResponseWriter, r *http.Request, metrics metrics.Metri
metrics.GatewayFunctions.Observe(seconds)
}
func makeProxy(metrics metrics.MetricOptions) http.HandlerFunc {
func lookupInvoke(w http.ResponseWriter, r *http.Request, metrics metrics.MetricOptions, name string) {
exists, err := lookupSwarmService(name)
if err != nil || exists == false {
if err != nil {
log.Fatalln(err)
}
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Error resolving service."))
}
if exists == true {
requestBody, _ := ioutil.ReadAll(r.Body)
invokeService(w, r, metrics, name, requestBody)
}
}
func makeProxy(metrics metrics.MetricOptions, wildcard bool) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
metrics.GatewayRequestsTotal.Inc()
......@@ -110,16 +127,15 @@ func makeProxy(metrics metrics.MetricOptions) http.HandlerFunc {
log.Println(r.Header)
header := r.Header["X-Function"]
log.Println(header)
if len(header) > 0 {
exists, err := lookupSwarmService(header[0])
if err != nil {
log.Fatalln(err)
}
if exists == true {
requestBody, _ := ioutil.ReadAll(r.Body)
invokeService(w, r, metrics, header[0], requestBody)
}
fmt.Println(wildcard)
if wildcard == true {
vars := mux.Vars(r)
name := vars["name"]
fmt.Println("invoke by name")
lookupInvoke(w, r, metrics, name)
} else if len(header) > 0 {
lookupInvoke(w, r, metrics, header[0])
} else {
requestBody, _ := ioutil.ReadAll(r.Body)
alexaService := isAlexa(requestBody)
......@@ -160,12 +176,16 @@ func main() {
prometheus.Register(GatewayServerlessServedTotal)
prometheus.Register(GatewayFunctions)
r := mux.NewRouter()
r.HandleFunc("/", makeProxy(metrics.MetricOptions{
metricsOptions := metrics.MetricOptions{
GatewayRequestsTotal: GatewayRequestsTotal,
GatewayServerlessServedTotal: GatewayServerlessServedTotal,
GatewayFunctions: GatewayFunctions,
}))
}
r := mux.NewRouter()
r.HandleFunc("/", makeProxy(metricsOptions, false))
r.HandleFunc("/function/{name:[a-zA-Z]+}", makeProxy(metricsOptions, true))
metricsHandler := metrics.PrometheusHandler()
r.Handle("/metrics", metricsHandler)
......
FROM golang:1.7.3
RUN mkdir -p /go/src/app
COPY handler.go /go/src/app
WORKDIR /go/src/app
RUN go get -d -v
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
COPY fwatchdog /usr/bin/
ENV fprocess="/go/src/app/app"
CMD ["fwatchdog"]
WebhookStash
============
Example serverless function shows how to stash way contents of webhooks called via API gateway.
Each file is saved with the UNIX timestamp in nano seconds plus an extension of .txt
Example:
```
# curl -X POST -v -d @$HOME/.ssh/id_rsa.pub localhost:8080/function/webhookstash
```
Then if you find the replica you can check the disk:
```
# docker exec webhookstash.1.z054csrh70tgk9s5k4bb8uefq find
```
package main
import (
"fmt"
"io/ioutil"
"os"
"strconv"
"time"
)
func main() {
input, _ := ioutil.ReadAll(os.Stdin)
fmt.Println("Stashing request")
now := time.Now()
stamp := strconv.FormatInt(now.UnixNano(), 10)
ioutil.WriteFile(stamp+".txt", input, 0644)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment