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.