Skip to content

Repository files navigation

go-bootstrap

A golang module to reduce common boilerplate code.

This module is shared between many golang tools in trivago and is very opinionated on the modules used in these tools. More precisely it expect tools to:

Maintenance and PRs

This repository is in active development but is not our main focus.
PRs are welcome, but will take some time to be reviewed.

License

All files in the repository are subject to the Apache 2.0 License

Builds and Releases

All commits to the main branch need to use conventional commits.
Releases will be generated automatically from these commits using Release Please.

Required tools

All required tools can be installed locally via nix and are loaded on demand via direnv.
On MacOS you can install nix via the installer from determinate systems.

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

We provided a justfile to generate the required .envrc file. Run just init-nix to get started, or run the script directly.

Running unit-tests

After you have set up your environment, run unittests via just test or

go test ./...

Examples

Minimal usage

This allows reading configuration flags via viper, sets up zerolog in a google cloud logging friendly way and makes the workload CGroup aware.

package main

import (
  "github.com/trivago/go-bootstrap/v2/config"
)

func main() {
  config.Read("CFG","config.yaml")
}

HTTP server

This extends the minimal example to let the workload serve HTTP with the standard library. Any framework that implements http.Handler can be passed the same way. See MIGRATION.md for upgrade notes.

package main

import (
  "log"
  "net/http"

  "github.com/trivago/go-bootstrap/v2/config"
  "github.com/trivago/go-bootstrap/v2/httpserver"
  "github.com/spf13/viper"
)

func main() {
  viper.SetDefault("port", 8080)
  config.Read("CFG","config.yaml")

  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
  })

  srv, err := httpserver.New(
    viper.GetInt("port"),
    httpserver.CheckOK,
    httpserver.CheckOK,
    mux,
  )
  if err != nil {
    log.Fatal(err)
  }

  httpserver.Listen(srv, nil)
}

Gin server

This creates a Gin engine inside the package and registers routes through an init callback. Existing Gin handlers and probe functions stay valid.

package main

import (
  "log"

  "github.com/gin-gonic/gin"
  "github.com/trivago/go-bootstrap/v2/config"
  "github.com/trivago/go-bootstrap/v2/httpserver"
  "github.com/spf13/viper"
)

func main() {
  viper.SetDefault("port", 8080)
  config.Read("CFG","config.yaml")

  handler := func(router *gin.Engine) {
    router.GET("/", func(c *gin.Context) {
      c.Status(200)
    })
  }

  srv, err := httpserver.NewGin(
    viper.GetInt("port"),
    httpserver.AlwaysOk,
    httpserver.AlwaysOk,
    handler,
  )
  if err != nil {
    log.Fatal(err)
  }

  httpserver.Listen(srv, nil)
}

FastHTTP server

This uses a native fasthttp server with the same probes, logging, recovery, and TLS options.

package main

import (
  "log"

  "github.com/trivago/go-bootstrap/v2/config"
  "github.com/trivago/go-bootstrap/v2/httpserver"
  "github.com/spf13/viper"
  "github.com/valyala/fasthttp"
)

func main() {
  viper.SetDefault("port", 8080)
  config.Read("CFG","config.yaml")

  handler := func(ctx *fasthttp.RequestCtx) {
    ctx.SetStatusCode(fasthttp.StatusOK)
  }

  srv, err := httpserver.NewFastHTTP(
    viper.GetInt("port"),
    httpserver.CheckOK,
    httpserver.CheckOK,
    handler,
  )
  if err != nil {
    log.Fatal(err)
  }

  httpserver.Listen(srv, nil)
}

HTTPs server

This example requires valid TLS certificates to be present as files. The [hack] directory contains some self-signed examples and a generator script for testing purposes.

Use NewWithConfig for net/http, or NewFastHTTPWithConfig for fasthttp.

net/http

package main

import (
  "log"
  "net/http"

  "github.com/trivago/go-bootstrap/v2/config"
  "github.com/trivago/go-bootstrap/v2/httpserver"
  "github.com/spf13/viper"
)

func main() {
  viper.SetDefault("port", 8443)
  viper.SetDefault("tls.cert", "/etc/certs/tls.crt")
  viper.SetDefault("tls.key", "/etc/certs/tls.key")

  config.Read("CFG","config.yaml")

  srv, err := httpserver.NewWithConfig(httpserver.Config{
    Port:        viper.GetInt("port"),
    PathTLSCert: viper.GetString("tls.cert"),
    PathTLSKey:  viper.GetString("tls.key"),
  }, http.NewServeMux())
  if err != nil {
    log.Fatal(err)
  }

  httpserver.Listen(srv, nil)
}

FastHTTP

package main

import (
  "log"

  "github.com/trivago/go-bootstrap/v2/config"
  "github.com/trivago/go-bootstrap/v2/httpserver"
  "github.com/spf13/viper"
  "github.com/valyala/fasthttp"
)

func main() {
  viper.SetDefault("port", 8443)
  viper.SetDefault("tls.cert", "/etc/certs/tls.crt")
  viper.SetDefault("tls.key", "/etc/certs/tls.key")

  config.Read("CFG","config.yaml")

  handler := func(ctx *fasthttp.RequestCtx) {
    ctx.SetStatusCode(fasthttp.StatusOK)
  }

  srv, err := httpserver.NewFastHTTPWithConfig(httpserver.Config{
    Port:        viper.GetInt("port"),
    PathTLSCert: viper.GetString("tls.cert"),
    PathTLSKey:  viper.GetString("tls.key"),
  }, handler)
  if err != nil {
    log.Fatal(err)
  }

  httpserver.Listen(srv, nil)
}

About

A golang module to reduce common boilerplate code

Resources

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages