mirror of
https://github.com/openfaas/faas.git
synced 2025-06-11 17:56:47 +00:00
Enable routing via /functions/ endpoint
This commit is contained in:
parent
f2fdfde43c
commit
84d1c0eaef
@ -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:
|
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
|
* 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:
|
Features:
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
echo Building catservice:latest
|
echo Building server:latest
|
||||||
|
|
||||||
docker build -t catservice .
|
|
||||||
|
|
||||||
|
docker build -t server .
|
||||||
|
@ -51,6 +51,7 @@ func lookupSwarmService(serviceName string) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error with Docker client.")
|
log.Fatal("Error with Docker client.")
|
||||||
}
|
}
|
||||||
|
fmt.Printf("Resolving: '%s'\n", serviceName)
|
||||||
serviceFilter := filters.NewArgs()
|
serviceFilter := filters.NewArgs()
|
||||||
serviceFilter.Add("name", serviceName)
|
serviceFilter.Add("name", serviceName)
|
||||||
services, err := c.ServiceList(context.Background(), types.ServiceListOptions{Filters: serviceFilter})
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(responseBody)
|
w.Write(responseBody)
|
||||||
seconds := time.Since(start).Seconds()
|
seconds := time.Since(start).Seconds()
|
||||||
fmt.Printf("[%s] took %f seconds\n", stamp, 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)
|
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) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
metrics.GatewayRequestsTotal.Inc()
|
metrics.GatewayRequestsTotal.Inc()
|
||||||
|
|
||||||
@ -110,16 +127,15 @@ func makeProxy(metrics metrics.MetricOptions) http.HandlerFunc {
|
|||||||
log.Println(r.Header)
|
log.Println(r.Header)
|
||||||
header := r.Header["X-Function"]
|
header := r.Header["X-Function"]
|
||||||
log.Println(header)
|
log.Println(header)
|
||||||
|
fmt.Println(wildcard)
|
||||||
|
|
||||||
if len(header) > 0 {
|
if wildcard == true {
|
||||||
exists, err := lookupSwarmService(header[0])
|
vars := mux.Vars(r)
|
||||||
if err != nil {
|
name := vars["name"]
|
||||||
log.Fatalln(err)
|
fmt.Println("invoke by name")
|
||||||
}
|
lookupInvoke(w, r, metrics, name)
|
||||||
if exists == true {
|
} else if len(header) > 0 {
|
||||||
requestBody, _ := ioutil.ReadAll(r.Body)
|
lookupInvoke(w, r, metrics, header[0])
|
||||||
invokeService(w, r, metrics, header[0], requestBody)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
requestBody, _ := ioutil.ReadAll(r.Body)
|
requestBody, _ := ioutil.ReadAll(r.Body)
|
||||||
alexaService := isAlexa(requestBody)
|
alexaService := isAlexa(requestBody)
|
||||||
@ -160,12 +176,16 @@ func main() {
|
|||||||
prometheus.Register(GatewayServerlessServedTotal)
|
prometheus.Register(GatewayServerlessServedTotal)
|
||||||
prometheus.Register(GatewayFunctions)
|
prometheus.Register(GatewayFunctions)
|
||||||
|
|
||||||
r := mux.NewRouter()
|
metricsOptions := metrics.MetricOptions{
|
||||||
r.HandleFunc("/", makeProxy(metrics.MetricOptions{
|
|
||||||
GatewayRequestsTotal: GatewayRequestsTotal,
|
GatewayRequestsTotal: GatewayRequestsTotal,
|
||||||
GatewayServerlessServedTotal: GatewayServerlessServedTotal,
|
GatewayServerlessServedTotal: GatewayServerlessServedTotal,
|
||||||
GatewayFunctions: GatewayFunctions,
|
GatewayFunctions: GatewayFunctions,
|
||||||
}))
|
}
|
||||||
|
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/", makeProxy(metricsOptions, false))
|
||||||
|
|
||||||
|
r.HandleFunc("/function/{name:[a-zA-Z]+}", makeProxy(metricsOptions, true))
|
||||||
|
|
||||||
metricsHandler := metrics.PrometheusHandler()
|
metricsHandler := metrics.PrometheusHandler()
|
||||||
r.Handle("/metrics", metricsHandler)
|
r.Handle("/metrics", metricsHandler)
|
||||||
|
11
sample-functions/WebhookStash/Dockerfile
Normal file
11
sample-functions/WebhookStash/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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"]
|
18
sample-functions/WebhookStash/README.md
Normal file
18
sample-functions/WebhookStash/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
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
|
||||||
|
```
|
18
sample-functions/WebhookStash/handler.go
Normal file
18
sample-functions/WebhookStash/handler.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
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)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user