Socket
Socket
Sign inDemoInstall

github.com/ikawaha/goa

Package Overview
Dependencies
0
Alerts
File Explorer

Install Socket

Detect and block malicious and high-risk dependencies

Install

    github.com/ikawaha/goa

Package goa provides the runtime support for goa microservices. 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 RequestData and ResponseData structs, error handling via error classes, middleware support via the Middleware data structure as well as decoding and encoding algorithms. The RequestData and ResponseData structs provides access to the request and response state. goa request handlers also accept a golang.org/x/net/Context interface as first parameter so that deadlines and cancelation signals may easily be implemented. The request state exposes the underlying http.Request object as well as the deserialized payload (request body) and parameters (both path and querystring parameters). Generated action specific contexts wrap the context.Context, ResponseData and RequestData data structures. They expose properly typed fields that correspond to the request parameters and body data structure descriptions appearing in the design. The response state exposes the response status and body length as well as the underlying ResponseWriter. 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): The action signature generated by goagen is: where UpdateBottleContext is: and implements: The definitions of the Bottle and UpdateBottlePayload data structures are ommitted for brievity. There is one controller interface generated per resource defined via the design language. The interface exposes the controller actions. 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.Controller which takes care of implementing the middleware handling. 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 corresponding Use methods. 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. The controller action methods generated by goagen such as the Update method of the BottleController interface shown above all return an error value. goa defines an Error struct that action implementations can use to describe the content of the corresponding HTTP response. Errors can be created using error classes which are functions created via NewErrorClass. The ErrorHandler middleware maps errors to HTTP responses. Errors that are instances of the Error struct are mapped using the struct fields while other types of errors return responses with status code 500 and the error message in the body. 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. 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 Encoder and Decoder 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 an invalid input or an unexpected condition produces a response that contains a structured error. The Error data structure contains four fields: a code, a status, a detail and metadata. The code defines the class of error (e.g. "invalid_parameter_type") and the status the corresponding HTTP status (e.g. 400). The detail contains a message specific to the error occurrence. The medata contains key/value pairs that provide contextual information (name of parameters, value of invalid parameter etc.). The basic data structure backing errors is Error. Instances of Error can be created via Error Class functions. See http://goa.design/implement/error_handling.html 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 return errors that get merged with any previously encountered error via the Error Merge method. goa includes an error handler middleware that takes care of mapping back any error returned by previously called middleware or action handler into HTTP responses. If the error is an instance of Error then the corresponding content including the HTTP status is used otherwise an internal error is returned. Errors that bubble up all the way to the top (i.e. not handled by the error middleware) also generate an internal error response.


Version published

Readme

Source

goa is a framework for building microservices in Go using a unique design-first approach.

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 these 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
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, "text/plain")
        })

})

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 operands.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
2016/04/05 20:39:10 [INFO] mount ctrl=Operands action=Add route=GET /add/:left/:right
2016/04/05 20:39:10 [INFO] mount file name=swagger/swagger.json route=GET /swagger.json
2016/04/05 20:39:10 [INFO] listen transport=http 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
CLI client for the adder service

Usage:
  adder-cli [command]

Available Commands:
  add         add returns the sum of the left and right parameters in the response body

Flags:
      --dump[=false]: Dump HTTP request and response.
  -H, --host="localhost:8080": API hostname
      --pp[=false]: Pretty print response body
  -s, --scheme="http": Set the requests scheme
  -t, --timeout=20s: Set the request timeout, defaults to 20s

Use "adder-cli [command] --help" for more information about a command.

To get information on how to call a specific API use:

$ ./adder-cli add operands --help
Usage:
  adder-cli add operands ["/add/:left/:right"] [flags]

Global Flags:
      --dump               Dump HTTP request and response.
  -H, --host string        API hostname (default "localhost:8080")
      --pp                 Pretty print response body
  -s, --scheme string      Set the requests scheme
  -t, --timeout duration   Set the request timeout (default 20s)

Now let's run it:

$ ./adder-cli add operands /add/1/2
2016/04/05 20:43:18 [INFO] started id=HffVaGiH GET=http://localhost:8080/add/1/2
2016/04/05 20:43:18 [INFO] completed id=HffVaGiH status=200 time=1.028827ms
3⏎

This also works:

$ ./adder-cli add operands --left=1 --right=2
2016/04/25 00:08:59 [INFO] started id=ouKmwdWp GET=http://localhost:8080/add/1/2
2016/04/25 00:08:59 [INFO] completed id=ouKmwdWp status=200 time=1.097749ms
3⏎     

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

2016/04/05 20:43:18 [INFO] started action=Add id=cASjgqGiCP-1 GET=/add/1/2
2016/04/05 20:43:18 [INFO] params action=Add id=cASjgqGiCP-1 right=2 left=1
2016/04/05 20:43:18 [INFO] completed action=Add id=cASjgqGiCP-1 status=0 bytes=0 time=36.615µs

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

./adder-cli add operands add/1/d
2016/04/05 20:44:56 [INFO] started id=5254tL8j GET=http://localhost:8080/add/1/d
2016/04/05 20:44:56 [INFO] completed id=5254tL8j status=500 time=840.12µs
error: 500: "Internal error: 400 invalid_request: invalid value \"d\" for parameter \"right\", must be a integer"

As you can see the generated code validated the incoming request 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

goa.design

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

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

Getting Started

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

Middleware

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

Examples

The examples repo contains simple examples illustrating basic concepts.

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 green) and send a PR over.

The issues contain entries tagged with help wanted: beginners which provide a great way to get started!

FAQs

Last updated on 02 May 2016

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc