mirror of
https://github.com/openfaas/faas.git
synced 2025-06-10 09:16:48 +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:
|
||||
|
||||
* 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:
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/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)
|
||||
fmt.Println(wildcard)
|
||||
|
||||
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)
|
||||
}
|
||||
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)
|
||||
|
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