github.com/furusax0621/goa-v1@v1.4.3/README.md (about)

     1  # <img src="http://goa.design/img/goa-logo.svg">
     2  
     3  goa is a framework for building micro-services and REST APIs in Go using a
     4  unique design-first approach.
     5  
     6  [![Build Status](https://travis-ci.org/goadesign/goa.svg?branch=master)](https://travis-ci.org/goadesign/goa)
     7  [![Windows Build status](https://ci.appveyor.com/api/projects/status/vixp37loj5i6qmaf/branch/master?svg=true)](https://ci.appveyor.com/project/RaphaelSimon/goa-oqtis/branch/master)
     8  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/goadesign/goa/blob/master/LICENSE)
     9  [![Godoc](https://godoc.org/github.com/goadesign/goa?status.svg)](https://godoc.org/gopkg.in/goadesign/goa.v1)
    10  [![Slack](https://img.shields.io/badge/slack-gophers-orange.svg?style=flat)](https://gophers.slack.com/messages/goa/)
    11  
    12  ## Why goa?
    13  
    14  goa takes a different approach to building micro-services. Instead of focusing
    15  solely on helping with implementation, goa makes it possible to describe the
    16  *design* of an API using a simple DSL. goa then uses that description to provide
    17  specialized helper code to the implementation and to generate documentation, API
    18  clients, tests, even custom artifacts.
    19  
    20  If DSLs are not your thing then consider this: you need to document your APIs so
    21  that clients (be it internal e.g. other services or external e.g. UIs) may
    22  consume them. Typically this requires maintaining a completely separate document
    23  (for example an OpenAPI specification). Making sure that the document stays
    24  up-to-date takes a lot of effort and at the end of the day you have to write
    25  that document - why not use a simple and clear Go DSL to do that instead?
    26  
    27  Another aspect to consider is the need for properly designing APIs and making
    28  sure that the design choices remain consistent across the endpoints or even
    29  across multiple APIs. If the source code is the only place where design
    30  decisions are kept then not only is it impossible to maintain consistency it's
    31  also difficult to think about the design in the first place. The goa DSL makes
    32  it possible to think about the design explicitly and - since it's code - to
    33  re-use design elements for consistency.
    34  
    35  The goa DSL allows writing self-explanatory code that describes the resources
    36  exposed by the API and for each resource the properties and actions. goa comes
    37  with the `goagen` tool which runs the DSL and generates various types of
    38  artifacts from the resulting data structures.
    39  
    40  One of the `goagen` output is glue code that binds your code with the underlying
    41  HTTP server. This code is specific to your API so that for example there is no
    42  need to cast or "bind" any handler argument prior to using them. Each generated
    43  handler has a signature that is specific to the corresponding resource action.
    44  It's not just the parameters though, each handler also has access to specific
    45  helper methods that generate the possible responses for that action. The DSL can
    46  also define validations in which case the generated code takes care of
    47  validating the incoming request parameters and payload prior to invoking the
    48  handler.
    49  
    50  The end result is controller code that is terse and clean, the boilerplate is
    51  all gone. Another big benefit is the clean separation of concern between design
    52  and implementation: on bigger projects it's often the case that API design
    53  changes require careful review, being able to generate a new version of the
    54  documentation without having to write a single line of implementation is a big
    55  boon.
    56  
    57  This idea of separating design and implementation is not new, the
    58  excellent [Praxis](http://praxis-framework.io) framework from RightScale follows
    59  the same pattern and was an inspiration to goa.
    60  
    61  ## Installation
    62  
    63  Goa v1 can be used with Go modules:
    64  
    65  ```bash
    66  export GO111MODULE=on
    67  go mod init <my project>
    68  go get github.com/goadesign/goa/...@v1
    69  ```
    70  
    71  Or without Go modules by cloning the repo first:
    72  
    73  ```bash
    74  cd $GOPATH/src
    75  mkdir -p github.com/goadesign
    76  cd github.com/goadesign
    77  git clone https://github.com/goadesign/goa
    78  cd goa; git checkout v1
    79  go get -v github.com/goadesign/goa/...
    80  ```
    81  
    82  ### Stable Versions
    83  
    84  goa follows [Semantic Versioning](http://semver.org/) which is a fancy way of saying it publishes
    85  releases with version numbers of the form `vX.Y.Z` and makes sure that your code can upgrade to new
    86  versions with the same `X` component without having to make changes.
    87  
    88  Releases are tagged with the corresponding version number. There is also a branch for each major
    89  version (only `v1` at the moment). The recommended practice is to vendor the stable branch.
    90  
    91  Current Release: `v1.4.3`
    92  Stable Branch: `v1`
    93  
    94  ## Teaser
    95  
    96  ### 1. Design
    97  
    98  Create the file `$GOPATH/src/goa-adder/design/design.go` with the following content:
    99  ```go
   100  package design
   101  
   102  import (
   103          . "github.com/goadesign/goa/design"
   104          . "github.com/goadesign/goa/design/apidsl"
   105  )
   106  
   107  var _ = API("adder", func() {
   108          Title("The adder API")
   109          Description("A teaser for goa")
   110          Host("localhost:8080")
   111          Scheme("http")
   112  })
   113  
   114  var _ = Resource("operands", func() {
   115          Action("add", func() {
   116                  Routing(GET("add/:left/:right"))
   117                  Description("add returns the sum of the left and right parameters in the response body")
   118                  Params(func() {
   119                          Param("left", Integer, "Left operand")
   120                          Param("right", Integer, "Right operand")
   121                  })
   122                  Response(OK, "text/plain")
   123          })
   124  
   125  })
   126  ```
   127  This file contains the design for an `adder` API which accepts HTTP GET requests to `/add/:x/:y`
   128  where `:x` and `:y` are placeholders for integer values. The API returns the sum of `x` and `y` in
   129  its body.
   130  
   131  ### 2. Implement
   132  
   133  Now that the design is done, let's run `goagen` on the design package:
   134  ```
   135  cd $GOPATH/src/goa-adder
   136  goagen bootstrap -d goa-adder/design
   137  ```
   138  This produces the following outputs:
   139  
   140  * `main.go` and `operands.go` contain scaffolding code to help bootstrap the implementation.
   141    running `goagen` again does not recreate them so that it's safe to edit their content.
   142  * an `app` package which contains glue code that binds the low level HTTP server to your
   143    implementation.
   144  * a `client` package with a `Client` struct that implements a `AddOperands` function which calls
   145    the API with the given arguments and returns the `http.Response`.
   146  * a `tool` directory that contains the complete source for a client CLI tool.
   147  * a `swagger` package with implements the `GET /swagger.json` API endpoint. The response contains
   148    the full Swagger specificiation of the API.
   149  
   150  ### 3. Run
   151  
   152  First let's implement the API - edit the file `operands.go` and replace the content of the `Add`
   153  function with:
   154  ```
   155  // Add import for strconv
   156  import "strconv"
   157  
   158  // Add runs the add action.
   159  func (c *OperandsController) Add(ctx *app.AddOperandsContext) error {
   160          sum := ctx.Left + ctx.Right
   161          return ctx.OK([]byte(strconv.Itoa(sum)))
   162  }
   163  ```
   164  Now let's compile and run the service:
   165  ```
   166  cd $GOPATH/src/goa-adder
   167  go build
   168  ./goa-adder
   169  2016/04/05 20:39:10 [INFO] mount ctrl=Operands action=Add route=GET /add/:left/:right
   170  2016/04/05 20:39:10 [INFO] listen transport=http addr=:8080
   171  ```
   172  Open a new console and compile the generated CLI tool:
   173  ```
   174  cd $GOPATH/src/goa-adder/tool/adder-cli
   175  go build
   176  ```
   177  The tool includes contextual help:
   178  ```
   179  ./adder-cli --help
   180  CLI client for the adder service
   181  
   182  Usage:
   183    adder-cli [command]
   184  
   185  Available Commands:
   186    add         add returns the sum of the left and right parameters in the response body
   187  
   188  Flags:
   189        --dump               Dump HTTP request and response.
   190    -H, --host string        API hostname (default "localhost:8080")
   191    -s, --scheme string      Set the requests scheme
   192    -t, --timeout duration   Set the request timeout (default 20s)
   193  
   194  Use "adder-cli [command] --help" for more information about a command.
   195  ```
   196  To get information on how to call a specific API use:
   197  ```
   198  ./adder-cli add operands --help
   199  Usage:
   200    adder-cli add operands [/add/LEFT/RIGHT] [flags]
   201  
   202  Flags:
   203        --left int    Left operand
   204        --pp          Pretty print response body
   205        --right int   Right operand
   206  
   207  Global Flags:
   208        --dump               Dump HTTP request and response.
   209    -H, --host string        API hostname (default "localhost:8080")
   210    -s, --scheme string      Set the requests scheme
   211    -t, --timeout duration   Set the request timeout (default 20s)
   212  ```
   213  Now let's run it:
   214  ```
   215  ./adder-cli add operands /add/1/2
   216  2016/04/05 20:43:18 [INFO] started id=HffVaGiH GET=http://localhost:8080/add/1/2
   217  2016/04/05 20:43:18 [INFO] completed id=HffVaGiH status=200 time=1.028827ms
   218  3⏎
   219  ```
   220  This also works:
   221  ```
   222  $ ./adder-cli add operands --left=1 --right=2
   223  2016/04/25 00:08:59 [INFO] started id=ouKmwdWp GET=http://localhost:8080/add/1/2
   224  2016/04/25 00:08:59 [INFO] completed id=ouKmwdWp status=200 time=1.097749ms
   225  3⏎
   226  ```
   227  The console running the service shows the request that was just handled:
   228  ```
   229  2016/06/06 10:23:03 [INFO] started req_id=rLAtsSThLD-1 GET=/add/1/2 from=::1 ctrl=OperandsController action=Add
   230  2016/06/06 10:23:03 [INFO] params req_id=rLAtsSThLD-1 right=2 left=1
   231  2016/06/06 10:23:03 [INFO] completed req_id=rLAtsSThLD-1 status=200 bytes=1 time=66.25µs
   232  ```
   233  Now let's see how robust our service is and try to use non integer values:
   234  ```
   235  ./adder-cli add operands add/1/d
   236  2016/06/06 10:24:22 [INFO] started id=Q2u/lPUc GET=http://localhost:8080/add/1/d
   237  2016/06/06 10:24:22 [INFO] completed id=Q2u/lPUc status=400 time=1.301083ms
   238  error: 400: {"code":"invalid_request","status":400,"detail":"invalid value \"d\" for parameter \"right\", must be a integer"}
   239  ```
   240  As you can see the generated code validated the incoming request against the types defined in the
   241  design.
   242  
   243  ### 4. Document
   244  
   245  The `swagger` directory contains the API Swagger (OpenAPI) specification in both
   246  YAML and JSON format.
   247  
   248  For open source projects hosted on
   249  github [swagger.goa.design](http://swagger.goa.design) provides a free service
   250  that renders the Swagger representation dynamically from goa design packages.
   251  Simply set the `url` query string with the import path to the design package.
   252  For example displaying the docs for `github.com/goadesign/goa-cellar/design` is
   253  done by browsing to:
   254  
   255  http://swagger.goa.design/?url=goadesign%2Fgoa-cellar%2Fdesign
   256  
   257  Note that the above generates the swagger spec dynamically and does not require it to be present in
   258  the Github repo.
   259  
   260  The Swagger JSON can also easily be served from the documented service itself using a simple
   261  [Files](http://goa.design/reference/goa/design/apidsl/#func-files-a-name-apidsl-files-a)
   262  definition in the design. Edit the file `design/design.go` and add:
   263  
   264  ```go
   265  var _ = Resource("swagger", func() {
   266          Origin("*", func() {
   267                 Methods("GET") // Allow all origins to retrieve the Swagger JSON (CORS)
   268          })
   269          Files("/swagger.json", "swagger/swagger.json")
   270  })
   271  ```
   272  
   273  Re-run `goagen bootstrap -d goa-adder/design` and note the new file
   274  `swagger.go` containing the implementation for a controller that serves the
   275  `swagger.json` file.
   276  
   277  Mount the newly generated controller by adding the following two lines to the `main` function in
   278  `main.go`:
   279  
   280  ```go
   281  cs := NewSwaggerController(service)
   282  app.MountSwaggerController(service, cs)
   283  ```
   284  
   285  Recompile and restart the service:
   286  
   287  ```
   288  ^C
   289  go build
   290  ./goa-adder
   291  2016/06/06 10:31:14 [INFO] mount ctrl=Operands action=Add route=GET /add/:left/:right
   292  2016/06/06 10:31:14 [INFO] mount ctrl=Swagger files=swagger/swagger.json route=GET /swagger.json
   293  2016/06/06 10:31:14 [INFO] listen transport=http addr=:8080
   294  ```
   295  
   296  Note the new route `/swagger.json`.  Requests made to it return the Swagger specification. The
   297  generated controller also takes care of adding the proper CORS headers so that the JSON may be
   298  retrieved from browsers using JavaScript served from a different origin (e.g. via Swagger UI). The
   299  client also has a new `download` action:
   300  
   301  ```
   302  cd tool/adder-cli
   303  go build
   304  ./adder-cli download --help
   305  Download file with given path
   306  
   307  Usage:
   308    adder-cli download [PATH] [flags]
   309  
   310  Flags:
   311        --out string   Output file
   312  
   313  Global Flags:
   314        --dump               Dump HTTP request and response.
   315    -H, --host string        API hostname (default "localhost:8080")
   316    -s, --scheme string      Set the requests scheme
   317    -t, --timeout duration   Set the request timeout (default 20s)
   318  ```
   319  
   320  Which can be used like this to download the file `swagger.json` in the current directory:
   321  
   322  ```
   323  ./adder-cli download swagger.json
   324  2016/06/06 10:36:24 [INFO] started file=swagger.json id=ciHL2VLt GET=http://localhost:8080/swagger.json
   325  2016/06/06 10:36:24 [INFO] completed file=swagger.json id=ciHL2VLt status=200 time=1.013307ms
   326  ```
   327  
   328  We now have a self-documenting API and best of all the documentation is automatically updated as the
   329  API design changes.
   330  
   331  ## Resources
   332  
   333  Consult the following resources to learn more about goa.
   334  
   335  ### goa.design
   336  
   337  [goa.design](https://goa.design) contains further information on goa including a getting
   338  started guide, detailed DSL documentation as well as information on how to implement a goa service.
   339  
   340  ### Examples
   341  
   342  The [examples](https://github.com/goadesign/examples) repo contains simple examples illustrating
   343  basic concepts.
   344  
   345  The [goa-cellar](https://github.com/goadesign/goa-cellar) repo contains the implementation for a
   346  goa service which demonstrates many aspects of the design language. It is kept up-to-date and
   347  provides a reference for testing functionality.
   348  
   349  ## Contributing
   350  
   351  Did you fix a bug? write docs or additional tests? or implement some new awesome functionality?
   352  You're a rock star!! Just make sure that `make` succeeds (or that TravisCI is green) and send a PR
   353  over.