{"id":19865636,"url":"https://github.com/openfaas/golang-http-template","last_synced_at":"2025-04-04T16:17:07.214Z","repository":{"id":38011508,"uuid":"118891044","full_name":"openfaas/golang-http-template","owner":"openfaas","description":"Golang templates for OpenFaaS using HTTP extensions","archived":false,"fork":false,"pushed_at":"2025-01-30T10:35:44.000Z","size":2083,"stargazers_count":105,"open_issues_count":1,"forks_count":58,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T15:11:22.716Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.openfaas.com/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openfaas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-25T09:21:22.000Z","updated_at":"2025-01-30T10:35:48.000Z","dependencies_parsed_at":"2023-11-10T12:52:48.478Z","dependency_job_id":"a86b5f06-0406-4618-b940-797ee2e4f5a1","html_url":"https://github.com/openfaas/golang-http-template","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fgolang-http-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fgolang-http-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fgolang-http-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fgolang-http-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openfaas","download_url":"https://codeload.github.com/openfaas/golang-http-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208190,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T15:23:31.631Z","updated_at":"2025-04-04T16:17:07.189Z","avatar_url":"https://github.com/openfaas.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenFaaS Golang HTTP templates\n\nThis 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.\n\nOur recommended template for Go developers is golang-middleware.\n\nYou'll find a chapter dedicated to writing functions with Go in [Everyday Golang by Alex Ellis](https://store.openfaas.com/l/everyday-golang)\n\nUsing the templates:\n\n```bash\nfaas-cli template store pull golang-http\nfaas-cli template store pull golang-middleware\n```\n\nOr:\n\n```bash\n$ faas template pull https://github.com/openfaas/golang-http-template\n$ faas new --list\n\nLanguages available as templates:\n- golang-http\n- golang-middleware\n```\n\nThe two templates are very similar:\n\n* `golang-middleware` implements a `http.HandleFunc` from Go's stdlib.\n* `golang-http` uses a structured request/response object\n\n## Dependencies\n\nYou can manage dependencies in one of the following ways:\n\n- 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\n- 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`\n- If you have a private module dependency, we recommend using the vendoring technique from above.\n\n### SSH authentication for private Git repositories and modules\n\nIf you do not wish to, or cannot use vendoring for some reason, then we provide an alternative set of templates for OpenFaaS Pro customers:\n\n* [OpenFaaS Pro templates for Go](https://github.com/openfaas/pro-templates)\n\n## 1.0 golang-middleware (recommended template)\n\nThis is one of the fastest templates available for Go available. Its signature is a [http.HandlerFunc](https://golang.org/pkg/net/http/#HandlerFunc), instead of a traditional request and response that you may expect from a function.\n\nThe user has complete control over the HTTP request and response.\n\n### Get the template\n\n```\n$ faas template store pull golang-middleware\n\n# Or\n\n$ faas template pull https://github.com/openfaas/golang-http-template\n$ faas new --lang golang-middleware \u003cfn-name\u003e\n```\n\n### Example usage\n\nExample writing a JSON response:\n\n```go\npackage function\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nfunc Handle(w http.ResponseWriter, r *http.Request) {\n\tvar input []byte\n\n\tif r.Body != nil {\n\t\tdefer r.Body.Close()\n\n\t\t// read request payload\n\t\treqBody, err := io.ReadAll(r.Body)\n\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\n\t\tinput = reqBody\n\t\t}\n\t}\n\n\t// log to stdout\n\tfmt.Printf(\"request body: %s\", string(input))\n\n\tresponse := struct {\n\t\tPayload     string              `json:\"payload\"`\n\t\tHeaders     map[string][]string `json:\"headers\"`\n\t\tEnvironment []string            `json:\"environment\"`\n\t}{\n\t\tPayload:     string(input),\n\t\tHeaders:     r.Header,\n\t\tEnvironment: os.Environ(),\n\t}\n\n\tresBody, err := json.Marshal(response)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n    // write result\n\tw.WriteHeader(http.StatusOK)\n\tw.Write(resBody)\n}\n```\n\nExample persistent database connection pool between function calls:\n\n```go\npackage function\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\n// db pool shared between function calls\nvar db *sql.DB\n\nfunc init() {\n\tvar err error\n\tdb, err = sql.Open(\"mysql\", \"user:password@/dbname\")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\n\terr = db.Ping()\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n\nfunc Handle(w http.ResponseWriter, r *http.Request) {\n\tvar query string\n\tctx := r.Context()\n\n\tif r.Body != nil {\n\t\tdefer r.Body.Close()\n\n\t\t// read request payload\n\t\tbody, err := io.ReadAll(r.Body)\n\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tquery = string(body)\n\t}\n\n\t// log to stdout\n\tfmt.Printf(\"Executing query: %s\", query)\n\n\trows, err := db.QueryContext(ctx, query)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer rows.Close()\n\n\tids := make([]string, 0)\n\tfor rows.Next() {\n\t\tif e := ctx.Err(); e != nil {\n\t\t\thttp.Error(w, e, http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tvar id int\n\t\tif err := rows.Scan(\u0026id); err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tids = append(ids, string(id))\n\t}\n\tif err := rows.Err(); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tresult := fmt.Sprintf(\"ids %s\", strings.Join(ids, \", \"))\n\n\t// write result\n\tw.WriteHeader(http.StatusOK)\n\tw.Write([]byte(result))\n}\n```\n\nExample retrieving request query strings\n\n```go\npackage function\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\nfunc Handle(w http.ResponseWriter, r *http.Request) {\n\t// Parses RawQuery and returns the corresponding\n\t// values as a map[string][]string\n\t// for more info https://golang.org/pkg/net/url/#URL.Query\n\tquery := r.URL.Query()\n\tw.WriteHeader(http.StatusOK)\n\tw.Write([]byte(fmt.Sprintf(\"id: %s\", query.Get(\"id\"))))\n}\n```\n\n### Adding static files to your image\n\nIf 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.\n\nTo read this back at runtime, you can do the following:\n\n```go\npackage function\n\nimport (\n    \"net/http\"\n    \"os\"\n)\n\nfunc Handle(w http.ResponseWriter, r *http.Request) {\n\n    data, err := os.ReadFile(\"./static/file.txt\")\n\n    if err != nil {\n        http.Error(w, err.Error(), http.StatusInternalServerError)\n    }\n\n    w.Write(data)\n}\n```\n\n## 2.0 golang-http\n\nThis template provides additional context and control over the HTTP response from your function.\n\n### Status of the template\n\nLike the `golang-middleware` template, this template is highly performant and suitable for production.\n\n### Get the template\n\n```sh\n$ faas template store pull golang-http\n\n# Or\n$ faas template pull https://github.com/openfaas/golang-http-template\n$ faas new --lang golang-http \u003cfn-name\u003e\n```\n\n### Example usage\n\nExample writing a successful message:\n\n```go\npackage function\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\thandler \"github.com/openfaas/templates-sdk/go-http\"\n)\n\n// Handle a function invocation\nfunc Handle(req handler.Request) (handler.Response, error) {\n\tvar err error\n\n\tmessage := fmt.Sprintf(\"Hello world, input was: %s\", string(req.Body))\n\n\treturn handler.Response{\n\t\tBody:       []byte(message),\n    }, err\n}\n```\n\nExample writing a custom status code\n\n```go\npackage function\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\thandler \"github.com/openfaas/templates-sdk/go-http\"\n)\n\n// Handle a function invocation\nfunc Handle(req handler.Request) (handler.Response, error) {\n\tvar err error\n\n\treturn handler.Response{\n\t\tBody:       []byte(\"Your workload was accepted\"),\n\t\tStatusCode: http.StatusAccepted,\n\t}, err\n}\n```\n\nExample writing an error / failure.\n\n```go\npackage function\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\t\thandler \"github.com/openfaas/templates-sdk/go-http\"\n)\n\n// Handle a function invocation\nfunc Handle(req handler.Request) (handler.Response, error) {\n\tvar err error\n\n\treturn handler.Response{\n        Body: []byte(\"the input was invalid\")\n\t}, fmt.Errorf(\"invalid input\")\n}\n```\n\nThe error will be logged to `stderr` and the `body` will be written to the client along with a HTTP 500 status code.\n\nExample reading a header.\n\n```go\npackage function\n\nimport (\n\t\"log\"\n\n\t\thandler \"github.com/openfaas/templates-sdk/go-http\"\n)\n\n// Handle a function invocation\nfunc Handle(req handler.Request) (handler.Response, error) {\n\tvar err error\n\n\tlog.Println(req.Header) // Check function logs for the request headers\n\n\treturn handler.Response{\n\t\tBody: []byte(\"This is the response\"),\n\t\tHeader: map[string][]string{\n\t\t\t\"X-Served-By\": []string{\"My Awesome Function\"},\n\t\t},\n\t}, err\n}\n```\n\nExample responding to an aborted request.\n\nThe `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()`\n\n```go\npackage function\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\n\thandler \"github.com/openfaas/templates-sdk/go-http\"\n)\n\n// Handle a function invocation\nfunc Handle(req handler.Request) (handler.Response, error) {\n\tvar err error\n\n\tfor i := 0; i \u003c 10000; i++ {\n\t\tif req.Context().Err() != nil  {\n\t\t\treturn handler.Response{}, fmt.Errorf(\"request cancelled\")\n\t\t}\n\t\tfmt.Printf(\"count %d\\n\", i)\n\t}\n\n\tmessage := fmt.Sprintf(\"Hello world, input was: %s\", string(req.Body))\n\treturn handler.Response{\n\t\tBody:       []byte(message),\n\t\tStatusCode: http.StatusOK,\n\t}, err\n}\n```\n\nThis context can also be passed to other methods so that they can respond to the cancellation as well, for example [`db.ExecContext(req.Context())`](https://golang.org/pkg/database/sql/#DB.ExecContext)\n\n\n#### Advanced usage\n\n##### Sub-packages\n\nIt is often natural to organize your code into sub-packages, for example you may have a function with the following structure\n\n```\n./echo\n├── go.mod\n├── go.sum\n├── handler.go\n└── pkg\n    └── version\n        └── version.go\n```\n\nNow if you want to reference the`version` sub-package, import it as\n\n```go\nimport \"handler/function/pkg/version\"\n```\n\nThis works like any local Go project.\n\n##### Go sub-modules\n\nSub-modules (meaning sub-folders with a `go.mod`) are not supported.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfaas%2Fgolang-http-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenfaas%2Fgolang-http-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfaas%2Fgolang-http-template/lists"}