• Stars
    star
    100
  • Rank 340,703 (Top 7 %)
  • Language
    Shell
  • License
    MIT License
  • Created almost 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Golang templates for OpenFaaS using HTTP extensions

OpenFaaS Golang HTTP templates

This repository contains two Golang templates for OpenFaaS which give additional control over the HTTP request and response. They will both handle higher throughput than the classic watchdog due to the process being kept warm.

Our recommended template for Go developers is golang-middleware.

You'll find a chapter dedicated to writing functions with Go in Everyday Golang by Alex Ellis

Using the templates:

faas-cli template store pull golang-http
faas-cli template store pull golang-middleware

Or:

$ faas template pull https://github.com/openfaas/golang-http-template
$ faas new --list

Languages available as templates:
- golang-http
- golang-middleware

The two templates are very similar:

  • golang-middleware implements a http.HandleFunc from Go's stdlib.
  • golang-http uses a structured request/response object

Dependencies

You can manage dependencies in one of the following ways:

  • To use Go modules without vendoring, the default already is set GO111MODULE=on but you also can make that explicit by adding --build-arg GO111MODULE=on to faas-cli up, you can also use --build-arg GOPROXY=https:// if you want to use your own mirror for the modules
  • You can also Go modules with vendoring, run go mod vendor in your function folder and add --build-arg GO111MODULE=off --build-arg GOFLAGS='-mod=vendor' to faas-cli up
  • If you have a private module dependency, we recommend using the vendoring technique from above.

SSH authentication for private Git repositories and modules

If you do not wish to, or cannot use vendoring for some reason, then we provide an alternative set of templates for OpenFaaS Pro customers:

1.0 golang-middleware (recommended template)

This is one of the fastest templates available for Go available. Its signature is a http.HandlerFunc, instead of a traditional request and response that you may expect from a function.

The user has complete control over the HTTP request and response.

Get the template

$ faas template store pull golang-middleware

# Or

$ faas template pull https://github.com/openfaas/golang-http-template
$ faas new --lang golang-middleware <fn-name>

Example usage

Example writing a JSON response:

package function

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

func Handle(w http.ResponseWriter, r *http.Request) {
	var input []byte

	if r.Body != nil {
		defer r.Body.Close()

		// read request payload
		reqBody, err := io.ReadAll(r.Body)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return

		input = reqBody
		}
	}

	// log to stdout
	fmt.Printf("request body: %s", string(input))

	response := struct {
		Payload     string              `json:"payload"`
		Headers     map[string][]string `json:"headers"`
		Environment []string            `json:"environment"`
	}{
		Payload:     string(input),
		Headers:     r.Header,
		Environment: os.Environ(),
	}

	resBody, err := json.Marshal(response)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

    // write result
	w.WriteHeader(http.StatusOK)
	w.Write(resBody)
}

Example persistent database connection pool between function calls:

package function

import (
	"database/sql"
	"fmt"
	"io"
	"net/http"
	"strings"
	_ "github.com/go-sql-driver/mysql"
)

// db pool shared between function calls
var db *sql.DB

func init() {
	var err error
	db, err = sql.Open("mysql", "user:password@/dbname")
	if err != nil {
		panic(err.Error())
	}

	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}
}

func Handle(w http.ResponseWriter, r *http.Request) {
	var query string
	ctx := r.Context()

	if r.Body != nil {
		defer r.Body.Close()

		// read request payload
		body, err := io.ReadAll(r.Body)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		query = string(body)
	}

	// log to stdout
	fmt.Printf("Executing query: %s", query)

	rows, err := db.QueryContext(ctx, query)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	ids := make([]string, 0)
	for rows.Next() {
		if e := ctx.Err(); e != nil {
			http.Error(w, e, http.StatusBadRequest)
			return
		}
		var id int
		if err := rows.Scan(&id); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		ids = append(ids, string(id))
	}
	if err := rows.Err(); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	result := fmt.Sprintf("ids %s", strings.Join(ids, ", "))

	// write result
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(result))
}

Example retrieving request query strings

package function
import (
	"fmt"
	"net/http"
)
func Handle(w http.ResponseWriter, r *http.Request) {
	// Parses RawQuery and returns the corresponding
	// values as a map[string][]string
	// for more info https://golang.org/pkg/net/url/#URL.Query
	query := r.URL.Query()
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(fmt.Sprintf("id: %s", query.Get("id"))))
}

Adding static files to your image

If a folder named static is found in the root of your function's source code, it will be copied into the final image published for your function.

To read this back at runtime, you can do the following:

package function

import (
    "net/http"
    "os"
)

func Handle(w http.ResponseWriter, r *http.Request) {

    data, err := os.ReadFile("./static/file.txt")

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }

    w.Write(data)
}

2.0 golang-http

This template provides additional context and control over the HTTP response from your function.

Status of the template

Like the golang-middleware template, this template is highly performant and suitable for production.

Get the template

$ faas template store pull golang-http

# Or
$ faas template pull https://github.com/openfaas/golang-http-template
$ faas new --lang golang-http <fn-name>

Example usage

Example writing a successful message:

package function

import (
	"fmt"
	"net/http"

		handler "github.com/openfaas/templates-sdk/go-http"
)

// Handle a function invocation
func Handle(req handler.Request) (handler.Response, error) {
	var err error

	message := fmt.Sprintf("Hello world, input was: %s", string(req.Body))

	return handler.Response{
		Body:       []byte(message),
    }, err
}

Example writing a custom status code

package function

import (
	"fmt"
	"net/http"

		handler "github.com/openfaas/templates-sdk/go-http"
)

// Handle a function invocation
func Handle(req handler.Request) (handler.Response, error) {
	var err error

	return handler.Response{
		Body:       []byte("Your workload was accepted"),
		StatusCode: http.StatusAccepted,
	}, err
}

Example writing an error / failure.

package function

import (
	"fmt"
	"net/http"

		handler "github.com/openfaas/templates-sdk/go-http"
)

// Handle a function invocation
func Handle(req handler.Request) (handler.Response, error) {
	var err error

	return handler.Response{
        Body: []byte("the input was invalid")
	}, fmt.Errorf("invalid input")
}

The error will be logged to stderr and the body will be written to the client along with a HTTP 500 status code.

Example reading a header.

package function

import (
	"log"

		handler "github.com/openfaas/templates-sdk/go-http"
)

// Handle a function invocation
func Handle(req handler.Request) (handler.Response, error) {
	var err error

	log.Println(req.Header) // Check function logs for the request headers

	return handler.Response{
		Body: []byte("This is the response"),
		Header: map[string][]string{
			"X-Served-By": []string{"My Awesome Function"},
		},
	}, err
}

Example responding to an aborted request.

The Request object provides access to the request context. This allows you to check if the request has been cancelled by using the context's done channel req.Context().Done() or the context's error req.Context().Err()

package function

import (
	"fmt"
	"net/http"

	handler "github.com/openfaas/templates-sdk/go-http"
)

// Handle a function invocation
func Handle(req handler.Request) (handler.Response, error) {
	var err error

	for i := 0; i < 10000; i++ {
		if req.Context().Err() != nil  {
			return handler.Response{}, fmt.Errorf("request cancelled")
		}
		fmt.Printf("count %d\n", i)
	}

	message := fmt.Sprintf("Hello world, input was: %s", string(req.Body))
	return handler.Response{
		Body:       []byte(message),
		StatusCode: http.StatusOK,
	}, err
}

This context can also be passed to other methods so that they can respond to the cancellation as well, for example db.ExecContext(req.Context())

Advanced usage

Sub-packages

It is often natural to organize your code into sub-packages, for example you may have a function with the following structure

./echo
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ handler.go
└── pkg
    └── version
        └── version.go

Now if you want to reference theversion sub-package, import it as

import "handler/function/pkg/version"

This works like any local Go project.

Go sub-modules

Sub-modules (meaning sub-folders with a go.mod) are not supported.

More Repositories

1

faas

OpenFaaS - Serverless Functions Made Simple
Go
24,942
star
2

faasd

A lightweight & portable faas engine
Go
2,550
star
3

faas-netes

Serverless Functions For Kubernetes
Go
2,122
star
4

workshop

Learn Serverless for Kubernetes with OpenFaaS
Python
955
star
5

faas-cli

Official CLI for OpenFaaS
Go
794
star
6

openfaas-cloud

The Multi-user OpenFaaS Platform
Go
767
star
7

templates

OpenFaaS Classic templates
Dockerfile
261
star
8

of-watchdog

Reverse proxy for STDIO and HTTP microservices
Go
244
star
9

ofc-bootstrap

Bootstrap OpenFaaS Cloud for your team
Go
181
star
10

store

Official Function and Template Store for OpenFaaS
Shell
162
star
11

faas-provider

A backend provider interface for OpenFaaS
Go
123
star
12

nats-queue-worker

Queue-worker for OpenFaaS with NATS Streaming
Go
122
star
13

openfaas-linkerd-workshop

Lightweight Serverless on Kubernetes with mTLS and traffic-splitting with Linkerd2
98
star
14

python-flask-template

HTTP and Flask-based OpenFaaS templates for Python 3
Python
82
star
15

faas-swarm

OpenFaaS provider for Docker Swarm
Go
79
star
16

ingress-operator

Custom domains, paths and TLS for your OpenFaaS Functions
Go
68
star
17

docs

Official Docs for OpenFaaS
65
star
18

community-cluster

OpenFaaS Cloud Cluster for Community
60
star
19

connector-sdk

SDK for connecting events to functions
Go
56
star
20

openfaas.github.io

Primary website / landing-page for the project
HTML
53
star
21

store-functions

Common CLIs packaged in containers with a HTTP interface
Dockerfile
51
star
22

media

Press kit / Media pack for OpenFaaS
44
star
23

cron-connector

Invoke functions on a schedule.
Go
39
star
24

nats-connector

An OpenFaaS event-connector to trigger functions from NATS
Go
38
star
25

mqtt-connector

MQTT connector for OpenFaaS
Go
32
star
26

cloud-functions

OpenFaaS social functions
Python
28
star
27

classic-watchdog

Classic Watchdog for OpenFaaS
Go
25
star
28

certifier

OpenFaaS Compliance testing
Go
25
star
29

license-check

Check your code for Copyright header compliance
Go
19
star
30

ruby-http

A Ruby HTTP template for OpenFaaS
Ruby
12
star
31

faas-middleware

HTTP middleware for OpenFaaS
Go
12
star
32

templates-sdk

SDK resources for templates such as models and entrypoints
Java
10
star
33

function-builder-examples

OpenFaaS Pro function builder API examples
PHP
10
star
34

social-functions

Enabling social media for OpenFaaS
Go
9
star
35

cli.openfaas.com

The installation script for the OpenFaaS CLI served by Netlify
Shell
9
star
36

python-fan-in-example

Python code example for implementing a fan-out/fan-in pattern with OpenFaaS functions.
Python
8
star
37

config-checker

Check your OpenFaaS Configuration
Go
7
star
38

astradb-openfaas

Connect to Astra DB using Node.js and OpenFaaS
JavaScript
3
star
39

go-sdk

An SDK for use within OpenFaaS functions
Go
3
star
40

openfaas-autoscaler-tests

JavaScript
2
star
41

derek-test-repo

Testing compliance
1
star
42

.github

README for organisation
1
star
43

multi-tenant-tests

Basic multi-tenant-tests
JavaScript
1
star