Categorygithub.com/cloudflare/service
modulepackage
0.0.0-20241016230021-e9bbb9bc8e78
Repository: https://github.com/cloudflare/service.git
Documentation: pkg.go.dev

# README

Service

The goal of this package is to quickly surface consistent and supportable JSON web services for small bits of business logic.

It is useful for two key scenarios:

  1. Wrapping small pieces of business logic in a web service
  2. Achieving consistency in the response structure

Features:

  • Parsing of JSON inputs
  • Rendering of JSON
  • Errors rendered as JSON
  • Pagination struct for consistent pagination by API consumers
  • Automatic HTTP OPTIONS
  • Automatic HTTP HEAD
  • glog-style logging interface
  • Sentry support if os.Getenv("SENTRY_DSN") is set
  • Middleware capability (via Negroni)
  • /_debug/profile/info.html for web based profiling
  • /_debug/pprof for pprof profiling
  • /_heartbeat basic version info
  • /_version endpoint that services can override with their own (i.e. to provide DB migration version information in addition to process version information)

External dependencies

go get github.com/codegangsta/negroni
go get github.com/getsentry/raven-go
go get github.com/mistifyio/negroni-pprof
go get github.com/unrolled/render
go get github.com/wblakecaldwell/profiler
go get github.com/coreos/go-oidc/jose
go get github.com/coreos/go-oidc/key
go get github.com/coreos/go-oidc/oidc

Usage

go get github.com/cloudflare/service

Create a new project, and in your main.go:

package main

import (
	"flag"

	"github.com/cloudflare/service"
)

func main() {
	// service/log requires that we call flag.Parse()
	flag.Parse()

	// Creates a new webservice, this holds all of the controllers
	ws := service.NewWebService()

	// Add a controller to the web service, a controller handles one path
	ws.AddWebController(HelloController())

	// Run the web service
	ws.Run(":8080")
}

In example.go:

package main

import (
	"net/http"

	"github.com/gorilla/mux"
	"github.com/cloudflare/service"
	"github.com/cloudflare/service/render"
)

// HelloController handles the /hello/{name} route
func HelloController() service.WebController {
	wc := service.NewWebController("/hello/{name}")

	// Add a handler for GET
	wc.AddMethodHandler(service.Get, HelloControllerGet)

	return wc
}

// HelloControllerGet handles GET for /hello/{name}
func HelloControllerGet(w http.ResponseWriter, req *http.Request) {
	// Get the path var for this controller
	name := mux.Vars(req)["name"]

	type HelloWorld struct {
		Hello string `json:"hello"`
	}

	hello := HelloWorld{Hello: name}

	render.JSON(w, http.StatusOK, hello)
}

Build and run the service, access via http://localhost:8080/hello/world.

Access http://localhost:8080/ for a list of the endpoints available and their methods, call http://localhost:8080/hello/world to see the above endpoint working.

Heartbeat and Versioning

To enable /_heartbeat to echo the git hash of the current build and the timestamp of the current build you will need to use a Makefile to build your executable. You will need to adjust your main.go to support this:

Your main.go:

package main

import "github.com/cloudflare/service"

var buildTag = "dev"
var buildDate = "0001-01-01T00:00:00Z"

func main() {
	service.BuildTag = buildTag
	service.BuildDate = buildDate
}

Your Makefile:

.PHONY: all build install

all: install

BUILD_TAG = $(shell git log --pretty=format:'%h' -n 1)
BUILD_DATE = $(shell date -u +%Y-%m-%dT%H:%M:%SZ)

build:
	@go build -ldflags "-X main.buildTag=$(BUILD_TAG) -X main.buildDate=$(BUILD_DATE)"
	@echo "build complete"

install:
	@go install -ldflags "-X main.buildTag=$(BUILD_TAG) -X main.buildDate=$(BUILD_DATE)"

Using Make to build using make build or to install using make install. Those will build and install in the same way that go build or go install will, but simply wrap the go command to ensure that the build information is added.

# Packages

No description provided by the author
Package log implements leveled logging.
No description provided by the author
No description provided by the author
No description provided by the author

# Functions

GetHandler returns a global handler for this route, to be used by the server mux.
GetHTTPMethod returns the method ID for the method in a HTTP request.
GetMethodID returns an int value for a valid HTTP method name (upper-cased).
GetMethodName returns the upper-cased method, i.e.
IsMethod returns true if the int value matches one of the iota values for a HTTP method.
NewWebController creates a new controller for a given route.
NewWebService provides a way to create a new blank WebService.

# Constants

HTTP Methods.
HTTP Methods.
HTTP Methods.
HTTP Methods.
HTTP Methods.
HTTP Methods.
Post
HTTP Methods.
HTTP Methods.
HTTP Methods.

# Variables

BuildDate is the date that this was compiled, or zeroes if no date is provided.
BuildTag is the git hash of the build, or "dev" if no hash is provided.
HeartbeatRoute is the path to the heartbeat endpoint.
VersionRoute is the path to the version information endpoint.

# Structs

EndPoint describes an endpoint that exists on this web service.
Message provides a simple JSON struct for serialising string messages as responses to calls that don't have a complex Type.
Version is the base struct returned by the /version endpoint.
WebController describes the HTTP method handlers for a given route.
WebService represents a web server with a collection of controllers.

# Type aliases

EndPoints is a slice of all endpoints on this web service.