goa

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

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

Go to latest
Published: Feb 8, 2016 License: MIT Imports: 29 Imported by: 0

README

goa

goa is a framework for building RESTful microservices in Go.

Build Status Windows Build status License Godoc Slack Intro

Why goa?

There are a number of good Go packages for writing modular web services out there so why build another one? Glad you asked! The existing packages tend to focus on providing small and highly modular frameworks that are purposefully narrowly focused. The intent is to keep things simple and to avoid mixing concerns.

This is great when writing simple APIs that tend to change rarely. However there are a number of problems that any non trivial API implementation must address. Things like request validation, response media type definitions or documentation are hard to do in a way that stays consistent and flexible as the API surface evolves.

goa takes a different approach to building web applications: instead of focusing solely on helping with implementation, goa makes it possible to describe the design of an API in an holistic way. goa then uses that description to provide specialized helper code to the implementation and to generate documentation, API clients, tests, even custom artifacts.

The goa design language allows writing self-explanatory code that describes the resources exposed by the API and for each resource the properties and actions. goa comes with the goagen tool which runs the design language and generates various types of artifacts from the resulting metadata.

One of the goagen output is glue code that binds your code with the underlying HTTP server. This code is specific to your API so that for example there is no need to cast or "bind" any handler argument prior to using them. Each generated handler has a signature that is specific to the corresponding resource action. It's not just the parameters though, each handler also has access to specific helper methods that generate the possible responses for that action. The metadata can also include validation rules so that the generated code also takes care of validating the incoming request parameters and payload prior to invoking your code.

The end result is controller code that is terse and clean, the boilerplate is all gone. Another big benefit is the clean separation of concern between design and implementation: on bigger projects it's often the case that API design changes require careful review, being able to generate a new version of the documentation without having to write a single line of implementation is a big boon.

This idea of separating design and implementation is not new, the excellent Praxis framework from RightScale follows the same pattern and was an inspiration to goa.

Other Whys and Hows

If you are new to goa I can't recommend enough that you read the Gopher Academy blog post. goa may look a little bit different at first, the post explains the thinking behind it so that you can better take advantage of the framework.

Installation

Assuming you have a working Go setup:

go get github.com/goadesign/goa/goagen

Teaser

1. Design

Create the file $GOPATH/src/goa-adder/design/design.go with the following content:

package design

import (
        . "github.com/goadesign/goa/design"
        . "github.com/goadesign/goa/design/apidsl"
)

var _ = API("adder", func() {
        Title("The adder API")
        Description("A teaser for goa")
        Host("localhost:8080")
        Scheme("http")
})

var _ = Resource("operands", func() {
        Action("add", func() {
                Routing(GET("add/:left/:right"))
                Description("add returns the sum of the left and right parameters in the response body")
                Params(func() {
                        Param("left", Integer, "Left operand")
                        Param("right", Integer, "Right operand")
                })
                Response(OK, "plain/text")
        })

})

This file contains the design for an adder API which accepts HTTP GET requests to /add/:x/:y where :x and :y are placeholders for integer values. The API returns the sum of x and y in its body.

2. Implement

Now that the design is done, let's run goagen on the design package:

$ cd $GOPATH/src/goa-adder
$ goagen bootstrap -d goa-adder/design

This produces the following outputs:

  • main.go and adder.go contain scaffolding code to help bootstrap the implementation. running goagen again does no recreate them so that it's safe to edit their content.
  • an app package which contains glue code that binds the low level HTTP server to your implementation.
  • a client package with a Client struct that implements a AddOperands function which calls the API with the given arguments and returns the http.Response. The client directory also contains the complete source for a client CLI tool (see below).
  • a swagger package with implements the GET /swagger.json API endpoint. The response contains the full Swagger specificiation of the API.
3. Run

First let's implement the API - edit the file operands.go and replace the content of the Add function with:

// Add runs the add action.
func (c *OperandsController) Add(ctx *app.AddOperandsContext) error {
        sum := ctx.Left + ctx.Right
        return ctx.OK([]byte(strconv.Itoa(sum)))
}

Now let's compile and run the service:

$ cd $GOPATH/src/goa-adder
$ go build
$ ./goa-adder
INFO[01-04|08:24:06] mount                                    app=API ctrl=Operands action=Add route="GET /add/:left/:right"
INFO[01-04|08:24:06] mount                                    app=API file=swagger/swagger.json route="GET /swagger.json"
INFO[01-04|08:24:06] listen                                   app=API addr=:8080

Open a new console and compile the generated CLI tool:

cd $GOPATH/src/goa-adder/client/adder-cli
go build

The tool includes contextual help:

$ ./adder-cli --help
usage: adder-cli [<flags>] <command> [<args> ...]

CLI client for the adder service

Flags:
      --help           Show context-sensitive help (also try --help-long and --help-man).
  -s, --scheme="http"  Set the requests scheme
  -h, --host=HOST      API hostname
  -t, --timeout=20s    Set the request timeout, defaults to 20s
      --dump           Dump HTTP request and response.
      --pp             Pretty print response body

Commands:
  help [<command>...]
    Show help.

  add operands <path>
    add adds the left and right parameters and returns the result
$ ./adder-cli add operands --help
usage: adder-cli add operands <path>

Args:
  <path>  Request path, format is /add/:left/:right

Now let's run it:

$ ./adder-cli add operands /add/1/2
INFO[01-04|08:30:43] started                                  id=+LG8rvid GET=http://localhost:8080/add/1/2
INFO[01-04|08:30:43] completed                                id=+LG8rvid status=200 time=842.472µs
3

The console running the service shows the request that was just handled:

INFO[01-04|08:30:43] started                                  app=API ctrl=OperandsController action=Add id=k5QShkGsd5-1 GET=/add/1/2
DBUG[01-04|08:30:43] params                                   app=API ctrl=OperandsController action=Add id=k5QShkGsd5-1 right=2 left=1
INFO[01-04|08:30:43] completed                                app=API ctrl=OperandsController action=Add id=k5QShkGsd5-1 status=200 bytes=1 time=61.176µs

Now let's see how robust our service is and try to use non integer values:

./adder-cli add operands add/1/d
INFO[01-04|08:32:53] started                                  id=hq3zYwXp GET=http://localhost:8080/add/1/d
INFO[01-04|08:32:53] completed                                id=hq3zYwXp status=400 time=847.297µs
error: 400: [{"id":1,"title":"invalid parameter value","msg":"invalid value \"d\" for parameter \"right\", must be a integer"}]

As you can see the generated code validated the incoming request state against the types defined in the design.

4. Document

The swagger directory contains the entire Swagger specification in the swagger.json file. The specification can also be accessed through the service:

$ curl localhost:8080/swagger.json

For open source services hosted on github swagger.goa.design provides a free service that renders the Swagger representation dynamically from goa design packages.

Resources

GoDoc
  • Package goa contains the data structures and algorithms used at runtime.
  • Package apidsl contains the implementation of the goa design language.
  • Package design defines the output data structures of the design language.
  • Package dslengine is a tool to parse and process any arbitrary DSL
Website

http://goa.design contains further information on goa.

Getting Started

Can't wait to give it a try? the easiest way is to follow the short getting started guide.

Middleware

The middleware repo provides a number of middlewares covering most common needs. It also provides a good source of examples for writing new middlewares.

Examples

The goa-cellar repo contains the implementation for a goa service which demonstrates many aspects of the design language. It is kept up-to-date and provides a reference for testing functionality.

Contributing

Did you fix a bug? write docs or additional tests? or implement some new awesome functionality? You're a rock star!! Just make sure that make succeeds (or that TravisCI is g104.197.54.215reen) and send a PR over.

And if you're looking for inspiration the wookie contains a roadmap document with many good suggestions...

Documentation

Overview

Package goa provides the runtime support for goa web services.

Code Generation

goa service development begins with writing the *design* of a service. The design is described using the goa language implemented by the github.com/goadesign/goa/design/apidsl package. The goagen tool consumes the metadata produced from executing the design language to generate service specific code that glues the underlying HTTP server with action specific code and data structures.

The goa package contains supporting functionality for the generated code including basic request and response state management through the Context data structure, error handling via the service and controller ErrorHandler field, middleware support via the Middleware data structure as well as input (and output) format validation algorithms.

Request Context

The Context data structure provides access to both the request and response state. It implements the golang.org/x/net/Context interface so that deadlines and cancelation signals may also be implemented with it.

The request state is accessible through the Get, GetMany and Payload methods which return the values of the request parameters, query strings and request body. Action specific contexts wrap Context and expose properly typed fields corresponding to the request parameters and body data structure descriptions appearing in the design.

The response state can be accessed through the ResponseStatus, ResponseLength and Header methods. The Context type implements the http.ResponseWriter interface and thus action contexts can be used in places http.ResponseWriter can. Action contexts provide action specific helper methods that write the responses as described in the design optionally taking an instance of the media type for responses that contain a body.

Here is an example showing an "update" action corresponding to following design (extract):

Resource("bottle", func() {
	DefaultMedia(Bottle)
	Action("update", func() {
		Params(func() {
			Param("bottleID", Integer)
		})
		Payload(UpdateBottlePayload)
		Response(OK)
		Response(NotFound)
	})
})

The action signature generated by goagen is:

type BottleController interface {
	goa.Controller
	Update(*UpdateBottleContext) error
}

where UpdateBottleContext is:

	type UpdateBottleContext struct {
        	*goa.Context
        	BottleID  int
        	Payload   *UpdateBottlePayload
	}

and implements:

func (ctx *UpdateBottleContext) OK(resp *Bottle) error
func (ctx *UpdateBottleContext) NotFound() error

The definitions of the Bottle and UpdateBottlePayload data structures are ommitted for brievity.

Controllers

There is one controller interface generated per resource defined via the design language. The interface exposes the controller actions as well as methods to set controller specific middleware and error handlers (see below). User code must provide data structures that implement these interfaces when mounting a controller onto a service. The controller data structure should include an anonymous field of type *goa.ApplicationController which takes care of implementing the middleware and error handler handling.

Error Handling

The controller action methods generated by goagen such as the Update method of the BottleController interface shown above all return an error value. The controller or service-wide error handler (if no controller specific error handler) function is invoked whenever the value returned by a controller action is not nil. The handler gets both the request context and the error as argument.

The default handler implementation returns a response with status code 500 containing the error message in the body. A different error handler can be specificied using the SetErrorHandler function on either a controller or service wide. goa comes with an alternative error handler - the TerseErrorHandler - which also returns a response with status 500 but does not write the error message to the body of the response.

Middleware

A goa middleware is a function that takes and returns a Handler. A Handler is a the low level function which handles incoming HTTP requests. goagen generates the handlers code so each handler creates the action specific context and calls the controller action with it.

Middleware can be added to a goa service or a specific controller using the Service type Use method. goa comes with a few stock middleware that handle common needs such as logging, panic recovery or using the RequestID header to trace requests across multiple services.

Validation

The goa design language documented in the dsl package makes it possible to attach validations to data structure definitions. One specific type of validation consists of defining the format that a data structure string field must follow. Example of formats include email, data time, hostnames etc. The ValidateFormat function provides the implementation for the format validation invoked from the code generated by goagen.

Encoding

The goa design language makes it possible to specify the encodings supported by the API both as input (Consumes) and output (Produces). goagen uses that information to registed the corresponding packages with the service encoders and decoders via the SetEncoder and SetDecoder methods. The service exposes the Decode, DecodeRequest, Encode and EncodeResponse that implement a simple content type negotiation algorithm for picking the right encoder for the "Accept" request header.

Package goa standardizes on structured error responses: a request that fails because of invalid input or unexpected condition produces a response that contains one or more structured error(s). Each error object has three keys: a id (number), a title and a message. The title for a given id is always the same, the intent is to provide a human friendly categorization. The message is specific to the error occurrence and provides additional details that often include contextual information (name of parameters etc.).

The basic data structure backing errors is TypedError which simply contains the id and message. Multiple errors (not just TypedError instances) can be encapsulated in a MultiError. Both TypedError and MultiError implement the error interface, the Error methods return valid JSON that can be written directly to a response body.

The code generated by goagen calls the helper functions exposed in this file when it encounters invalid data (wrong type, validation errors etc.) such as InvalidParamTypeError, InvalidAttributeTypeError etc. These methods take and return an error which is a MultiError that gets built over time. The final MultiError object then gets serialized into the response and sent back to the client. The response status code is inferred from the type wrapping the error object: a BadRequestError produces a 400 status code while any other error produce a 500. This behavior can be overridden by setting a custom ErrorHandler in the application.

Index

Constants

View Source
const (
	// ErrInvalidParamType is the error produced by the generated code when
	// a request parameter type does not match the design.
	ErrInvalidParamType = iota + 1

	// ErrMissingParam is the error produced by the generated code when a
	// required request parameter is missing.
	ErrMissingParam

	// ErrInvalidAttributeType is the error produced by the generated
	// code when a data structure attribute type does not match the design
	// definition.
	ErrInvalidAttributeType

	// ErrMissingAttribute is the error produced by the generated
	// code when a data structure attribute required by the design
	// definition is missing.
	ErrMissingAttribute

	// ErrInvalidEnumValue is the error produced by the generated code when
	// a values does not match one of the values listed in the attribute
	// definition as being valid (i.e. not part of the enum).
	ErrInvalidEnumValue

	// ErrMissingHeader is the error produced by the generated code when a
	// required header is missing.
	ErrMissingHeader

	// ErrInvalidFormat is the error produced by the generated code when
	// a value does not match the format specified in the attribute
	// definition.
	ErrInvalidFormat

	// ErrInvalidPattern is the error produced by the generated code when
	// a value does not match the regular expression specified in the
	// attribute definition.
	ErrInvalidPattern

	// ErrInvalidRange is the error produced by the generated code when
	// a value is less than the minimum specified in the design definition
	// or more than the maximum.
	ErrInvalidRange

	// ErrInvalidLength is the error produced by the generated code when
	// a value is a slice with less elements than the minimum length
	// specified in the design definition or more elements than the
	// maximum length.
	ErrInvalidLength

	// ErrInvalidVersion is the error rendered by the default mux when a
	// request specifies an invalid version.
	ErrInvalidVersion
)
View Source
const (
	// FormatDateTime defines RFC3339 date time values.
	FormatDateTime Format = "date-time"

	// FormatEmail defines RFC5322 email addresses.
	FormatEmail = "email"

	// FormatHostname defines RFC1035 Internet host names.
	FormatHostname = "hostname"

	// FormatIPv4 defines RFC2373 IPv4 address values.
	FormatIPv4 = "ipv4"

	// FormatIPv6 defines RFC2373 IPv6 address values.
	FormatIPv6 = "ipv6"

	// FormatURI defines RFC3986 URI values.
	FormatURI = "uri"

	// FormatMAC defines IEEE 802 MAC-48, EUI-48 or EUI-64 MAC address values.
	FormatMAC = "mac"

	// FormatCIDR defines RFC4632 and RFC4291 CIDR notation IP address values.
	FormatCIDR = "cidr"

	// FormatRegexp Regexp defines regular expression syntax accepted by RE2.
	FormatRegexp = "regexp"
)

Variables

View Source
var (
	// Log is the global logger from which other loggers (e.g. request specific loggers) are
	// derived. Configure it by setting its handler prior to calling New.
	// See https://godoc.org/github.com/inconshreveable/log15
	Log log.Logger

	// RootContext is the root context from which all request contexts are derived.
	// Set values in the root context prior to starting the server to make these values
	// available to all request handlers:
	//
	//	goa.RootContext = goa.RootContext.WithValue(key, value)
	//
	RootContext context.Context
)

InterruptSignals is the list of signals that initiate graceful shutdown. Note that only SIGINT is supported on Windows so this list should be overridden by the caller when running on that platform.

Functions

func Cancel

func Cancel()

Cancel sends a cancellation signal to all handlers through the action context. see https://godoc.org/golang.org/x/net/context for details on how to handle the signal.

func DefaultErrorHandler

func DefaultErrorHandler(ctx *Context, e error)

DefaultErrorHandler returns a 400 response for request validation errors (instances of BadRequestError) and a 500 response for other errors. It writes the error message to the response body in both cases.

func DefaultMissingVersionHandler

func DefaultMissingVersionHandler(ctx *Context, version string)

DefaultMissingVersionHandler returns a 400 response with a typed error in the body containing the name of the version that was targeted by the request.

func Fatal

func Fatal(msg string, ctx ...interface{})

Fatal logs a critical message and exits the process with status code 1. This function is meant to be used by initialization code to prevent the application from even starting up when something is obviously wrong. In particular this function should probably not be used when serving requests.

func InvalidAttributeTypeError

func InvalidAttributeTypeError(ctx string, val interface{}, expected string, err error) error

InvalidAttributeTypeError appends a typed error of id ErrIncompatibleType to err and returns it.

func InvalidEnumValueError

func InvalidEnumValueError(ctx string, val interface{}, allowed []interface{}, err error) error

InvalidEnumValueError appends a typed error of id ErrInvalidEnumValue to err and returns it.

func InvalidFormatError

func InvalidFormatError(ctx, target string, format Format, formatError, err error) error

InvalidFormatError appends a typed error of id ErrInvalidFormat to err and returns it.

func InvalidLengthError

func InvalidLengthError(ctx string, target interface{}, ln, value int, min bool, err error) error

InvalidLengthError appends a typed error of id ErrInvalidLength to err and returns it.

func InvalidParamTypeError

func InvalidParamTypeError(name string, val interface{}, expected string, err error) error

InvalidParamTypeError appends a typed error of id ErrInvalidParamType to err and returns it.

func InvalidPatternError

func InvalidPatternError(ctx, target string, pattern string, err error) error

InvalidPatternError appends a typed error of id ErrInvalidPattern to err and returns it.

func InvalidRangeError

func InvalidRangeError(ctx string, target interface{}, value int, min bool, err error) error

InvalidRangeError appends a typed error of id ErrInvalidRange to err and returns it.

func MissingAttributeError

func MissingAttributeError(ctx, name string, err error) error

MissingAttributeError appends a typed error of id ErrMissingAttribute to err and returns it.

func MissingHeaderError

func MissingHeaderError(name string, err error) error

MissingHeaderError appends a typed error of id ErrMissingHeader to err and returns it.

func MissingParamError

func MissingParamError(name string, err error) error

MissingParamError appends a typed error of id ErrMissingParam to err and returns it.

func ReportError

func ReportError(err error, err2 error) error

ReportError coerces the first argument into a MultiError then appends the second argument and returns the resulting MultiError.

func TerseErrorHandler

func TerseErrorHandler(ctx *Context, e error)

TerseErrorHandler behaves like DefaultErrorHandler except that it does not write to the response body for internal errors.

func ValidateFormat

func ValidateFormat(f Format, val string) error

ValidateFormat validates a string against a standard format. It returns nil if the string conforms to the format, an error otherwise. The format specification follows the json schema draft 4 validation extension. see http://json-schema.org/latest/json-schema-validation.html#anchor105 Supported formats are: - "date-time": RFC3339 date time value - "email": RFC5322 email address - "hostname": RFC1035 Internet host name - "ipv4" and "ipv6": RFC2673 and RFC2373 IP address values - "uri": RFC3986 URI value - "mac": IEEE 802 MAC-48, EUI-48 or EUI-64 MAC address value - "cidr": RFC4632 and RFC4291 CIDR notation IP address value - "regexp": Regular expression syntax accepted by RE2

func ValidatePattern

func ValidatePattern(p string, val string) bool

ValidatePattern returns an error if val does not match the regular expression p. It makes an effort to minimize the number of times the regular expression needs to be compiled.

Types

type Application

type Application struct {
	log.Logger // Application logger
	// contains filtered or unexported fields
}

Application represents a goa application. At the basic level an application consists of a set of controllers, each implementing a given resource actions. goagen generates global functions - one per resource - that make it possible to mount the corresponding controller onto an application. An application contains the middleware, logger and error handler shared by all its controllers. Setting up an application might look like:

api := goa.New("my api")
api.Use(SomeMiddleware())
rc := NewResourceController()
rc.Use(SomeOtherMiddleware())
app.MountResourceController(api, rc)
api.ListenAndServe(":80")

where NewResourceController returns an object that implements the resource actions as defined by the corresponding interface generated by goagen.

func (Application) Decode

func (ver Application) Decode(v interface{}, body io.Reader, contentType string) error

Decode uses registered Decoders to unmarshal a body based on the contentType

func (Application) DecodeRequest

func (ver Application) DecodeRequest(ctx *Context, v interface{}) error

DecodeRequest retrives the request body and `Content-Type` header and uses Decode to unmarshal into the provided `interface{}`

func (Application) EncodeResponse

func (ver Application) EncodeResponse(ctx *Context, v interface{}) error

EncodeResponse uses registered Encoders to marshal the response body based on the request `Accept` header and writes it to the http.ResponseWriter

func (*Application) ErrorHandler

func (app *Application) ErrorHandler() ErrorHandler

ErrorHandler returns the currently set error handler.

func (*Application) ListenAndServe

func (app *Application) ListenAndServe(addr string) error

ListenAndServe starts a HTTP server and sets up a listener on the given host/port.

func (*Application) ListenAndServeTLS

func (app *Application) ListenAndServeTLS(addr, certFile, keyFile string) error

ListenAndServeTLS starts a HTTPS server and sets up a listener on the given host/port.

func (*Application) Name

func (app *Application) Name() string

Name returns the application name.

func (*Application) NewController

func (app *Application) NewController(resName string) Controller

NewController returns a controller for the given resource. This method is mainly intended for use by the generated code. User code shouldn't have to call it directly.

func (*Application) ServeFiles

func (app *Application) ServeFiles(path, filename string) error

ServeFiles replies to the request with the contents of the named file or directory. The logic for what to do when the filename points to a file vs. a directory is the same as the standard http package ServeFile function. The path may end with a wildcard that matches the rest of the URL (e.g. *filepath). If it does the matching path is appended to filename to form the full file path, so:

ServeFiles("/index.html", "/www/data/index.html")

Returns the content of the file "/www/data/index.html" when requests are sent to "/index.html" and:

ServeFiles("/assets/*filepath", "/www/data/assets")

returns the content of the file "/www/data/assets/x/y/z" when requests are sent to "/assets/x/y/z".

func (*Application) ServeMux

func (app *Application) ServeMux() ServeMux

ServeMux returns the top level service mux.

func (Application) SetDecoder

func (ver Application) SetDecoder(f DecoderFactory, makeDefault bool, contentTypes ...string)

SetDecoder sets a specific decoder to be used for the specified content types. If a decoder is already registered, it will be overwritten.

func (Application) SetEncoder

func (ver Application) SetEncoder(f EncoderFactory, makeDefault bool, contentTypes ...string)

SetEncoder sets a specific encoder to be used for the specified content types. If an encoder is already registered, it will be overwritten.

func (*Application) SetErrorHandler

func (app *Application) SetErrorHandler(handler ErrorHandler)

SetErrorHandler defines an application wide error handler. The default error handler (DefaultErrorHandler) responds with a 500 status code and the error message in the response body. TerseErrorHandler provides an alternative implementation that does not write the error message to the response body for internal errors (e.g. for production). Set it with SetErrorHandler(TerseErrorHandler). Controller specific error handlers should be set using the Controller type SetErrorHandler method instead.

func (*Application) SetMissingVersionHandler

func (app *Application) SetMissingVersionHandler(handler MissingVersionHandler)

SetMissingVersionHandler registers the service missing version handler.

func (*Application) Use

func (app *Application) Use(m Middleware)

Use adds a middleware to the application wide middleware chain. See NewMiddleware for wrapping goa and http handlers into goa middleware. goa comes with a set of commonly used middleware, see middleware.go. Controller specific middleware should be mounted using the Controller type Use method instead.

func (*Application) Version

func (app *Application) Version(name string) ServiceVersion

Version returns an object that implements ServiceVersion based on the version name. If there is no version registered, it will instantiate a new version.

func (Application) VersionName

func (ver Application) VersionName() string

VersionName returns the version name.

type ApplicationController

type ApplicationController struct {
	log.Logger // Controller logger
	// contains filtered or unexported fields
}

ApplicationController provides the common state and behavior for generated controllers.

func (*ApplicationController) ErrorHandler

func (ctrl *ApplicationController) ErrorHandler() ErrorHandler

ErrorHandler returns the currently set error handler.

func (*ApplicationController) HandleError

func (ctrl *ApplicationController) HandleError(ctx *Context, err error)

HandleError invokes the controller error handler or - if there isn't one - the service error handler.

func (*ApplicationController) HandleFunc

func (ctrl *ApplicationController) HandleFunc(name string, h, d Handler) HandleFunc

HandleFunc wraps al request handler into a HandleFunc. The HandleFunc initializes the request context by loading the request state, invokes the handler and in case of error invokes the controller (if there is one) or application error handler. This function is intended for the controller generated code. User code should not need to call it directly.

func (*ApplicationController) MiddlewareChain

func (ctrl *ApplicationController) MiddlewareChain() []Middleware

MiddlewareChain returns the controller middleware chain.

func (*ApplicationController) SetErrorHandler

func (ctrl *ApplicationController) SetErrorHandler(handler ErrorHandler)

SetErrorHandler defines a controller specific error handler. When a controller action returns an error goa checks whether the controller is equipped with a error handler and if so calls it with the error given as argument. If there is no controller error handler then goa calls the application wide error handler instead.

func (*ApplicationController) Use

func (ctrl *ApplicationController) Use(m Middleware)

Use adds a middleware to the controller. See NewMiddleware for wrapping goa and http handlers into goa middleware. goa comes with a set of commonly used middleware, see middleware.go.

type BadRequestError

type BadRequestError struct {
	Actual error
}

BadRequestError is the type of errors that result in a response with status code 400.

func NewBadRequestError

func NewBadRequestError(err error) *BadRequestError

NewBadRequestError wraps the given error into a BadRequestError.

func (*BadRequestError) Error

func (b *BadRequestError) Error() string

Error implements error.

type BasicSigner

type BasicSigner struct {
	// Username is the basic auth user.
	Username string
	// Password is err guess what? the basic auth password.
	Password string
}

BasicSigner implements basic auth.

func (*BasicSigner) RegisterFlags

func (s *BasicSigner) RegisterFlags(app *cobra.Command)

RegisterFlags adds the "--user" and "--pass" flags to the client tool.

func (*BasicSigner) Sign

func (s *BasicSigner) Sign(req *http.Request) error

Sign adds the basic auth header to the request.

type Client

type Client struct {
	// Logger is the logger used to log client requests.
	log15.Logger
	// Client is the underlying http client.
	*http.Client
	// Signers contains the ordered list of request signers. A signer may add headers,
	// cookies etc. to a request generally to perform auth.
	Signers []Signer
	// Scheme is the HTTP scheme used to make requests to the API host.
	Scheme string
	// Host is the service hostname.
	Host string
	// UserAgent is the user agent set in requests made by the client.
	UserAgent string
	// Dump indicates whether to dump request response.
	Dump bool
}

Client is the command client data structure for all goa service clients.

func NewClient

func NewClient() *Client

NewClient create a new API client.

func (*Client) Do

func (c *Client) Do(req *http.Request) (*http.Response, error)

Do wraps the underlying http client Do method and adds logging.

type Context

type Context struct {
	context.Context // Underlying context
	log.Logger      // Context logger
}

Context is the object that provides access to the underlying HTTP request and response state. Context implements http.ResponseWriter and also provides helper methods for writing HTTP responses. It also implements the context.Context interface described at http://blog.golang.org/context.

func NewContext

func NewContext(gctx context.Context,
	service Service,
	req *http.Request,
	rw http.ResponseWriter,
	params url.Values) *Context

NewContext builds a goa context from the given context.Context and request state. If gctx is nil then context.Background is used instead.

func (*Context) AllParams

func (ctx *Context) AllParams() url.Values

AllParams return all URL and querystring parameters.

func (*Context) BadRequest

func (ctx *Context) BadRequest(err *BadRequestError) error

BadRequest sends a HTTP response with status code 400 and the given error as body.

func (*Context) Bug

func (ctx *Context) Bug(format string, a ...interface{}) error

Bug sends a HTTP response with status code 500 and the given body. The body can be set using a format and substituted values a la fmt.Printf.

func (*Context) Get

func (ctx *Context) Get(name string) string

Get returns the param or querystring value with the given name.

func (*Context) GetMany

func (ctx *Context) GetMany(name string) []string

GetMany returns the querystring values with the given name or nil if there aren't any.

func (*Context) GetNames

func (ctx *Context) GetNames() []string

GetNames returns all the querystring and URL parameter names.

func (*Context) Header

func (ctx *Context) Header() http.Header

Header returns the response header. It implements the http.ResponseWriter interface.

func (*Context) RawPayload

func (ctx *Context) RawPayload() interface{}

RawPayload returns the deserialized request body or nil if body is empty.

func (*Context) Request

func (ctx *Context) Request() *http.Request

Request returns the underlying HTTP request.

func (*Context) Respond

func (ctx *Context) Respond(code int, body interface{}) error

Respond serializes the given body matching the request Accept header against the service encoders. It uses the default service encoder if no match is found.

func (*Context) RespondBytes

func (ctx *Context) RespondBytes(code int, body []byte) error

RespondBytes writes the given HTTP status code and response body. This method should only be called once per request.

func (*Context) ResponseLength

func (ctx *Context) ResponseLength() int

ResponseLength returns the response body length in bytes if the response was written to the context via one of the response methods (Respond, JSON, BadRequest, Bug), 0 otherwise.

func (*Context) ResponseStatus

func (ctx *Context) ResponseStatus() int

ResponseStatus returns the response status if it was set via one of the context response methods (Respond, JSON, BadRequest, Bug), 0 otherwise.

func (*Context) ResponseWritten

func (ctx *Context) ResponseWritten() bool

ResponseWritten returns true if an HTTP response was written.

func (*Context) Service

func (ctx *Context) Service() Service

Service returns the underlying service.

func (*Context) SetPayload

func (ctx *Context) SetPayload(payload interface{})

SetPayload initializes the unmarshaled request body value.

func (*Context) SetResponseWriter

func (ctx *Context) SetResponseWriter(rw http.ResponseWriter) http.ResponseWriter

SetResponseWriter overrides the context underlying response writer. It returns the response writer that was previously set.

func (*Context) SetValue

func (ctx *Context) SetValue(key, val interface{})

SetValue sets the value associated with key in the context. The value can be retrieved using the Value method. Note that this changes the underlying context.Context object and thus clients holding a reference to that won't be able to access the new value. It's probably a bad idea to hold a reference to the inner context anyway...

func (*Context) Write

func (ctx *Context) Write(body []byte) (int, error)

Write writes the HTTP response body. It implements the http.ResponseWriter interface.

func (*Context) WriteHeader

func (ctx *Context) WriteHeader(code int)

WriteHeader writes the HTTP status code to the response. It implements the http.ResponseWriter interface.

type Controller

type Controller interface {
	log.Logger

	// Use adds a middleware to the controller middleware chain.
	// It is a convenient method for doing append(ctrl.MiddlewareChain(), m)
	Use(Middleware)

	// MiddlewareChain returns the controller middleware chain including the
	// service-wide middleware.
	MiddlewareChain() []Middleware

	// ErrorHandler returns the currently set error handler.
	ErrorHandler() ErrorHandler

	// SetErrorHandler sets the controller specific error handler.
	SetErrorHandler(ErrorHandler)

	// HandleFunc returns a HandleFunc from the given handler
	// name is used solely for logging.
	HandleFunc(name string, h, d Handler) HandleFunc
}

Controller is the interface implemented by all goa controllers. A controller implements a given resource actions. There is a one-to-one relationship between designed resources and generated controllers. Controllers may override the service wide error handler and be equipped with controller specific middleware.

type DecodeFunc

type DecodeFunc func(*Context, io.ReadCloser, interface{}) error

DecodeFunc is the function that initialize the unmarshaled payload from the request body.

type Decoder

type Decoder interface {
	Decode(v interface{}) error
}

A Decoder unmarshals an io.Reader into an interface

type DecoderFactory

type DecoderFactory interface {
	NewDecoder(r io.Reader) Decoder
}

A DecoderFactory generates custom decoders

func GobDecoderFactory

func GobDecoderFactory() DecoderFactory

GobDecoderFactory returns a struct that can generate new gob.Decoders

func JSONDecoderFactory

func JSONDecoderFactory() DecoderFactory

JSONDecoderFactory returns a struct that can generate new json.Decoders

func XMLDecoderFactory

func XMLDecoderFactory() DecoderFactory

XMLDecoderFactory returns a struct that can generate new xml.Decoders

type DefaultMux

type DefaultMux struct {
	SelectVersionFunc SelectVersionFunc
	// contains filtered or unexported fields
}

DefaultMux is the default goa mux. It dispatches requests to the appropriate version mux using a SelectVersionFunc. The default func is DefaultVersionFunc, change it with SelectVersion.

func (DefaultMux) Handle

func (m DefaultMux) Handle(method, path string, handle HandleFunc)

Handle sets the handler for the given verb and path.

func (DefaultMux) Lookup

func (m DefaultMux) Lookup(method, path string) HandleFunc

Lookup returns the HandleFunc associated with the given method and path.

func (*DefaultMux) SelectVersion

func (m *DefaultMux) SelectVersion(sv SelectVersionFunc)

SelectVersion sets the func used to compute the API version targetted by a request.

func (*DefaultMux) ServeHTTP

func (m *DefaultMux) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP is the function called back by the underlying HTTP server to handle incoming requests.

type Encoder

type Encoder interface {
	Encode(v interface{}) error
}

An Encoder marshals from an interface into an io.Writer

type EncoderFactory

type EncoderFactory interface {
	NewEncoder(w io.Writer) Encoder
}

A EncoderFactory generates custom encoders

func GobEncoderFactory

func GobEncoderFactory() EncoderFactory

GobEncoderFactory returns a struct that can generate new gob.Encoders

func JSONEncoderFactory

func JSONEncoderFactory() EncoderFactory

JSONEncoderFactory returns a struct that can generate new json.Encoders

func XMLEncoderFactory

func XMLEncoderFactory() EncoderFactory

XMLEncoderFactory returns a struct that can generate new xml.Encoders

type Encoding

type Encoding interface {
	// DecodeRequest uses registered Decoders to unmarshal the request body based on
	// the request "Content-Type" header.
	DecodeRequest(ctx *Context, v interface{}) error

	// EncodeResponse uses registered Encoders to marshal the response body based on the
	// request "Accept" header and writes the result to the http.ResponseWriter.
	EncodeResponse(ctx *Context, v interface{}) error

	// SetDecoder registers a decoder for the given content types.
	// If makeDefault is true then the decoder is used to decode payloads where none of
	// the registered decoders support the request content type.
	SetDecoder(f DecoderFactory, makeDefault bool, contentTypes ...string)

	// SetEncoder registers an encoder for the given content types.
	// If makeDefault is true then the encoder is used to encode bodies where none of
	// the registered encoders match the request "Accept" header.
	SetEncoder(f EncoderFactory, makeDefault bool, contentTypes ...string)
}

Encoding contains the encoding and decoding support.

type ErrorHandler

type ErrorHandler func(*Context, error)

ErrorHandler defines the application error handler signature.

type ErrorID

type ErrorID int

ErrorID is an enum listing the possible types of errors.

func (ErrorID) Title

func (k ErrorID) Title() string

Title returns a human friendly error title

type Format

type Format string

Format defines a validation format.

type GracefulApplication

type GracefulApplication struct {
	*Application
	sync.Mutex

	// Interrupted is true if the application is in the process of shutting down.
	Interrupted bool

	// CancelOnShutdown tells whether existing requests should be canceled when shutdown is
	// triggered (true) or whether to wait until the requests complete (false).
	CancelOnShutdown bool
	// contains filtered or unexported fields
}

GracefulApplication is a goa application using a graceful shutdown server. When sending any of the signals listed in InterruptSignals to the process GracefulApplication:

* disables keepalive connections.

* closes the listening socket, allowing another process to listen on that port immediately.

* calls Cancel, signaling all active handlers.

func (GracefulApplication) Decode

func (ver GracefulApplication) Decode(v interface{}, body io.Reader, contentType string) error

Decode uses registered Decoders to unmarshal a body based on the contentType

func (GracefulApplication) DecodeRequest

func (ver GracefulApplication) DecodeRequest(ctx *Context, v interface{}) error

DecodeRequest retrives the request body and `Content-Type` header and uses Decode to unmarshal into the provided `interface{}`

func (GracefulApplication) EncodeResponse

func (ver GracefulApplication) EncodeResponse(ctx *Context, v interface{}) error

EncodeResponse uses registered Encoders to marshal the response body based on the request `Accept` header and writes it to the http.ResponseWriter

func (*GracefulApplication) ListenAndServe

func (gapp *GracefulApplication) ListenAndServe(addr string) error

ListenAndServe starts the HTTP server and sets up a listener on the given host/port.

func (*GracefulApplication) ListenAndServeTLS

func (gapp *GracefulApplication) ListenAndServeTLS(addr, certFile, keyFile string) error

ListenAndServeTLS starts a HTTPS server and sets up a listener on the given host/port.

func (GracefulApplication) SetDecoder

func (ver GracefulApplication) SetDecoder(f DecoderFactory, makeDefault bool, contentTypes ...string)

SetDecoder sets a specific decoder to be used for the specified content types. If a decoder is already registered, it will be overwritten.

func (GracefulApplication) SetEncoder

func (ver GracefulApplication) SetEncoder(f EncoderFactory, makeDefault bool, contentTypes ...string)

SetEncoder sets a specific encoder to be used for the specified content types. If an encoder is already registered, it will be overwritten.

func (*GracefulApplication) Shutdown

func (gapp *GracefulApplication) Shutdown() bool

Shutdown initiates graceful shutdown of the running server once. Returns true on initial shutdown and false if already shutting down.

func (GracefulApplication) VersionName

func (ver GracefulApplication) VersionName() string

VersionName returns the version name.

type HandleFunc

type HandleFunc func(http.ResponseWriter, *http.Request, url.Values)

HandleFunc provides the implementation for an API endpoint. The values include both the querystring and path parameter values.

type Handler

type Handler func(*Context) error

Handler defines the controller handler signatures. Controller handlers accept a context and return an error. The context provides typed access to the request and response state. It implements the golang.org/x/net/context package Context interface so that handlers may define deadlines and cancelation signals - see the Timeout middleware as an example. If a controller handler returns an error then the application error handler is invoked with the request context and the error. The error handler is responsible for writing the HTTP response. See DefaultErrorHandler and TerseErrorHandler.

type JWTSigner

type JWTSigner struct {
	// Header is the name of the HTTP header which contains the JWT.
	// The default is "Authentication"
	Header string
	// Format represents the format used to render the JWT.
	// The default is "Bearer %s"
	Format string
	// contains filtered or unexported fields
}

JWTSigner implements JSON Web Token auth.

func (*JWTSigner) RegisterFlags

func (s *JWTSigner) RegisterFlags(app *cobra.Command)

RegisterFlags adds the "--jwt" flag to the client tool.

func (*JWTSigner) Sign

func (s *JWTSigner) Sign(req *http.Request) error

Sign adds the JWT auth header.

type Middleware

type Middleware func(Handler) Handler

Middleware represents the canonical goa middleware signature.

func NewMiddleware

func NewMiddleware(m interface{}) (mw Middleware, err error)

NewMiddleware creates a middleware from the given argument. The allowed types for the argument are:

- a goa middleware: goa.Middleware or func(goa.Handler) goa.Handler

- a goa handler: goa.Handler or func(*goa.Context) error

- an http middleware: func(http.Handler) http.Handler

- or an http handler: http.Handler or func(http.ResponseWriter, *http.Request)

An error is returned if the given argument is not one of the types above.

type MissingVersionHandler

type MissingVersionHandler func(*Context, string)

MissingVersionHandler defines the function that handles requests targetting a non existant API version.

type MultiError

type MultiError []error

MultiError records multiple errors.

func (MultiError) Error

func (m MultiError) Error() string

Error summarizes all the underlying error messages in one JSON array.

type OAuth2Signer

type OAuth2Signer struct {
	// RefreshURLFormat is a format that generates the refresh access token URL given a
	// refresh token.
	RefreshURLFormat string
	// RefreshToken contains the OAuth2 refresh token from which access tokens are
	// created.
	RefreshToken string
	// contains filtered or unexported fields
}

OAuth2Signer enables the use of OAuth2 refresh tokens. It takes care of creating access tokens given a refresh token and a refresh URL as defined in RFC 6749. Note that this signer does not concern itself with generating the initial refresh token, this has to be done prior to using the client. Also it assumes the response of the refresh request response is JSON encoded and of the form:

{
	"access_token":"2YotnFZFEjr1zCsicMWpAA",
	"expires_in":3600,
	"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA"
}

where the "expires_in" and "refresh_token" properties are optional and additional properties are ignored. If the response contains a "expires_in" property then the signer takes care of making refresh requests prior to the token expiration.

func (*OAuth2Signer) Refresh

func (s *OAuth2Signer) Refresh() error

Refresh makes a OAuth2 refresh access token request.

func (*OAuth2Signer) RegisterFlags

func (s *OAuth2Signer) RegisterFlags(app *cobra.Command)

RegisterFlags adds the "--refreshURL" and "--refreshToken" flags to the client tool.

func (*OAuth2Signer) Sign

func (s *OAuth2Signer) Sign(req *http.Request) error

Sign refreshes the access token if needed and adds the OAuth header.

type ResettableDecoder

type ResettableDecoder interface {
	Decoder
	Reset(r io.Reader)
}

The ResettableDecoder is used to determine whether or not a Decoder can be reset and thus safely reused in a sync.Pool

type ResettableEncoder

type ResettableEncoder interface {
	Encoder
	Reset(w io.Writer)
}

The ResettableEncoder is used to determine whether or not a Encoder can be reset and thus safely reused in a sync.Pool

type SelectVersionFunc

type SelectVersionFunc func(*http.Request) string

SelectVersionFunc is used by the default goa mux to compute the API version targetted by a given request. The default implementation looks for a version as path prefix. Alternate implementations can be set using the DefaultMux SelectVersion method.

func CombineSelectVersionFunc

func CombineSelectVersionFunc(funcs ...SelectVersionFunc) SelectVersionFunc

CombineSelectVersionFunc returns a SelectVersionFunc that tries each func passed as argument in order and returns the first non-empty string version.

func HeaderSelectVersionFunc

func HeaderSelectVersionFunc(header string) SelectVersionFunc

HeaderSelectVersionFunc returns a SelectVersionFunc that looks for the version in the header with the given name.

func PathSelectVersionFunc

func PathSelectVersionFunc(pattern, zeroVersion string) SelectVersionFunc

PathSelectVersionFunc returns a SelectVersionFunc that uses the given path pattern to extract the version from the request path. Use the same path pattern given in the DSL to define the API base path, e.g. "/api/:api_version". If the pattern matches zeroVersion then the empty version is returned (i.e. the unversioned controller handles the request).

func QuerySelectVersionFunc

func QuerySelectVersionFunc(query string) SelectVersionFunc

QuerySelectVersionFunc returns a SelectVersionFunc that looks for the version in the querystring with the given key.

type ServeMux

type ServeMux interface {
	http.Handler
	// Handle sets the HandleFunc for a given HTTP method and path.
	Handle(method, path string, handle HandleFunc)
	// Lookup returns the HandleFunc associated with the given HTTP method and path.
	Lookup(method, path string) HandleFunc
}

ServeMux is the interface implemented by the service request muxes. There is one instance of ServeMux per service version and one for requests targetting no version. It implements http.Handler and makes it possible to register request handlers for specific HTTP methods and request path via the Handle method.

func NewMux

func NewMux(app *Application) ServeMux

NewMux returns the default service mux implementation.

type Service

type Service interface {
	// Logging methods, configure the log handler using the Logger global variable.
	log.Logger

	// Encoding manages the service decoders and encoders.
	Encoding

	// Name is the name of the goa application.
	Name() string

	// Use adds a middleware to the service-wide middleware chain.
	Use(m Middleware)

	// ErrorHandler returns the currently set error handler, useful for middleware.
	ErrorHandler() ErrorHandler

	// SetErrorHandler registers the service-wide error handler.
	SetErrorHandler(ErrorHandler)

	// SetMissingVersionHandler registers the handler invoked when a request targets a
	// non existant API version.
	SetMissingVersionHandler(MissingVersionHandler)

	// ServeMux returns the service mux.
	ServeMux() ServeMux

	// ListenAndServe starts a HTTP server on the given port.
	ListenAndServe(addr string) error

	// ListenAndServeTLS starts a HTTPS server on the given port.
	ListenAndServeTLS(add, certFile, keyFile string) error

	// ServeFiles replies to the request with the contents of the named file or
	// directory. The logic // for what to do when the filename points to a file vs. a
	// directory is the same as the standard http package ServeFile function. The path
	// may end with a wildcard that matches the rest of the URL (e.g. *filepath). If it
	// does the matching path is appended to filename to form the full file path, so:
	// 	ServeFiles("/index.html", "/www/data/index.html")
	// Returns the content of the file "/www/data/index.html" when requests are sent to
	// "/index.html" and:
	//	ServeFiles("/assets/*filepath", "/www/data/assets")
	// returns the content of the file "/www/data/assets/x/y/z" when requests are sent
	// to "/assets/x/y/z".
	ServeFiles(path, filename string) error

	// Version returns an object that implements ServiceVersion based on the version name.
	// If there is no version registered, it will instantiate a new version.
	Version(name string) ServiceVersion

	// Decode uses registered Decoders to unmarshal a body based on the contentType
	Decode(v interface{}, body io.Reader, contentType string) error

	// NewController returns a controller for the resource with the given name.
	// This method is mainly intended for use by generated code.
	NewController(resName string) Controller
}

Service is the interface implemented by all goa services. It provides methods for configuring a service and running it.

func New

func New(name string) Service

New instantiates an application with the given name and default decoders/encoders.

func NewGraceful

func NewGraceful(name string, cancelOnShutdown bool) Service

NewGraceful returns a goa application that uses a graceful shutdown server.

type ServiceVersion

type ServiceVersion interface {
	// Encoding manages the version decoders and encoders.
	Encoding

	// VersionName returns the version name.
	VersionName() string

	// ServeMux returns the version request mux.
	ServeMux() ServeMux
}

ServiceVersion is the interface for interacting with individual service versions.

type Signer

type Signer interface {
	// Sign adds required headers, cookies etc.
	Sign(*http.Request) error
	// RegisterFlags registers the command line flags that defines the values used to
	// initialize the signer.
	RegisterFlags(cmd *cobra.Command)
}

Signer is the common interface implemented by all signers.

type TypedError

type TypedError struct {
	ID   ErrorID
	Mesg string
}

TypedError describes an error that can be returned in a HTTP response.

func (*TypedError) Error

func (t *TypedError) Error() string

Error builds an error message from the typed error details.

func (*TypedError) MarshalJSON

func (t *TypedError) MarshalJSON() ([]byte, error)

MarshalJSON implements the json marshaler interface.

Directories

Path Synopsis
_integration_tests
Package design defines types which describe the data types used by action controllers.
Package design defines types which describe the data types used by action controllers.
apidsl
Package apidsl implements the goa design language.
Package apidsl implements the goa design language.
apidsl/test
Package test contains a self-contained DSL test.
Package test contains a self-contained DSL test.
codegen
Package codegen contains common code used by all code generators.
Package codegen contains common code used by all code generators.
gen_client
Package genclient provides a generator for the client tool and package of a goa application.
Package genclient provides a generator for the client tool and package of a goa application.
gen_gen
Package gengen provides goagen with the ability to run user provided generators (*plugins*).
Package gengen provides goagen with the ability to run user provided generators (*plugins*).
gen_js
Package genjs provides a goa generator for a javascript client module.
Package genjs provides a goa generator for a javascript client module.
gen_main
Package genmain provides a generator for a skeleton goa application.
Package genmain provides a generator for a skeleton goa application.
gen_schema
Package genschema provides a generator for the JSON schema controller.
Package genschema provides a generator for the JSON schema controller.
gen_swagger
Package genswagger provides a generator for the JSON swagger controller.
Package genswagger provides a generator for the JSON swagger controller.
meta
Package meta is used to bootstrap the code generator.
Package meta is used to bootstrap the code generator.

Jump to

Keyboard shortcuts

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