service

package module
v0.0.0-...-e9bbb9b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2024 License: BSD-2-Clause Imports: 14 Imported by: 9

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.

Documentation

Index

Constants

View Source
const (
	Options = iota
	Head
	Post
	Get
	Put
	Patch
	Delete
	Connect
	Trace
)

HTTP Methods

Variables

View Source
var BuildDate = "0001-01-01T00:00:00Z"

BuildDate is the date that this was compiled, or zeroes if no date is provided

View Source
var BuildTag = "dev"

BuildTag is the git hash of the build, or "dev" if no hash is provided

View Source
var HeartbeatRoute string = `/_heartbeat`

HeartbeatRoute is the path to the heartbeat endpoint

View Source
var VersionRoute string = `/_version`

VersionRoute is the path to the version information endpoint

Functions

func GetHTTPMethod

func GetHTTPMethod(req *http.Request) int

GetHTTPMethod returns the method ID for the method in a HTTP request

func GetHandler

func GetHandler(
	wc WebController,
) func(w http.ResponseWriter, req *http.Request)

GetHandler returns a global handler for this route, to be used by the server mux

func GetMethodID

func GetMethodID(method string) int

GetMethodID returns an int value for a valid HTTP method name (upper-cased)

func GetMethodName

func GetMethodName(m int) string

GetMethodName returns the upper-cased method, i.e. GET for a given method int value

func IsMethod

func IsMethod(m int) bool

IsMethod returns true if the int value matches one of the iota values for a HTTP method

Types

type EndPoint

type EndPoint struct {
	URL     string `json:"href"`
	Methods string `json:"methods"`
}

EndPoint describes an endpoint that exists on this web service

type EndPoints

type EndPoints []EndPoint

EndPoints is a slice of all endpoints on this web service

func (EndPoints) Len

func (slice EndPoints) Len() int

func (EndPoints) Less

func (slice EndPoints) Less(i, j int) bool

func (EndPoints) Swap

func (slice EndPoints) Swap(i, j int)

type Message

type Message struct {
	Message string `json:"message"`
}

Message provides a simple JSON struct for serialising string messages as responses to calls that don't have a complex Type

type Version

type Version struct {
	BuildTag  string `json:"build"`
	BuildDate string `json:"buildDate"`
	Command   string `json:"command"`
}

Version is the base struct returned by the /version endpoint

func (*Version) Hydrate

func (v *Version) Hydrate()

Hydrate will fill in the Build and Command fields of the Version struct given

type WebController

type WebController struct {
	Route string
	// contains filtered or unexported fields
}

WebController describes the HTTP method handlers for a given route. Create a WebController with service.NewController(route)

func NewWebController

func NewWebController(route string) WebController

NewWebController creates a new controller for a given route

func (*WebController) AddMethodHandler

func (wc *WebController) AddMethodHandler(m int, h func(w http.ResponseWriter, req *http.Request))

AddMethodHandler adds a HTTP handler to a given HTTP method

func (*WebController) GetAllowedMethods

func (wc *WebController) GetAllowedMethods() string

GetAllowedMethods returns a comma-delimited string of HTTP methods allowed by this controller. This is determined by examining which methods have handlers assigned to them.

func (*WebController) GetMethodHandler

func (wc *WebController) GetMethodHandler(m int) func(w http.ResponseWriter, req *http.Request)

GetMethodHandler returns the appropriate method handler for the request or a Method Not Allowed handler

type WebService

type WebService struct {
	// contains filtered or unexported fields
}

WebService represents a web server with a collection of controllers

func NewWebService

func NewWebService() WebService

NewWebService provides a way to create a new blank WebService

func (*WebService) AddWebController

func (ws *WebService) AddWebController(wc WebController)

AddWebController allows callees to add their controller. Note: The order in which the controllers are added is the order in which the routes will be applied.

func (*WebService) BuildRouter

func (ws *WebService) BuildRouter() *mux.Router

BuildRouter collects all of the controllers, wires up the routes and returns the resulting router

func (*WebService) Run

func (ws *WebService) Run(addr string)

Run collects all of the controllers, wires up the routes and starts the server

Directories

Path Synopsis
Package log implements leveled logging.
Package log implements leveled logging.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL