github.com/kaisawind/go-swagger@v0.19.0/docs/tutorial/todo-list.md (about)

     1  # Todo List Tutorial
     2  
     3  This example walks you through a hypothetical project, building a todo list.
     4  
     5  It uses a todo list because this is well-understood application, so you can focus on the go-swagger pieces. In this example we build a server and a client.
     6  
     7  <!--more-->
     8  
     9  To create your application start with `swagger init`:
    10  
    11  ```
    12  swagger init spec \
    13    --title "A Todo list application" \
    14    --description "From the todo list tutorial on goswagger.io" \
    15    --version 1.0.0 \
    16    --scheme http \
    17    --consumes application/io.goswagger.examples.todo-list.v1+json \
    18    --produces application/io.goswagger.examples.todo-list.v1+json
    19  ```
    20  
    21  This gives you a skeleton `swagger.yml` file:
    22  
    23  ```yaml
    24  ---
    25  consumes:
    26  - application/io.goswagger.examples.todo-list.v1+json
    27  definitions: {}
    28  info:
    29    description: From the todo list tutorial on goswagger.io
    30    title: A Todo list application
    31    version: 1.0.0
    32  paths: {}
    33  produces:
    34  - application/io.goswagger.examples.todo-list.v1+json
    35  schemes:
    36  - http
    37  swagger: "2.0"
    38  ```
    39  
    40  This doesn't do much but it does pass validation:
    41  
    42  ```
    43  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list
    44  git:(master) ✗ ? » swagger validate ./swagger.yml
    45  The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
    46  ```
    47  
    48  Now that you have an empty but valid specification document, it's time to declare some models and endpoints for the API. You'll need a model to represent a todo item, so you can define that in the definitions section:
    49  
    50  ```yaml
    51  ---
    52  definitions:
    53    item:
    54      type: object
    55      required:
    56        - description
    57      properties:
    58        id:
    59          type: integer
    60          format: int64
    61          readOnly: true
    62        description:
    63          type: string
    64          minLength: 1
    65        completed:
    66          type: boolean
    67  ```
    68  
    69  In this model definition we say that the model `item` is an _object_ with a required property `description`. This item model has 3 properties: `id`, `description`, and `completed`. The `id` property is an int64 value and is marked as _readOnly_, meaning that it will be provided by the API server and it will be ignored when the item is created.
    70  
    71  This document also says that the description must be at least 1 char long, which results in a string property that's [not a pointer](/use/schemas.md#nullability).
    72  
    73  At this moment you have enough so that actual code could be generated, but let's continue defining the rest of the API so that the code generation will be more useful. Now that you have a model so you can add some endpoints to list the todo's:
    74  
    75  ```yaml
    76  ---
    77  paths:
    78    /:
    79      get:
    80        tags:
    81          - todos
    82        responses:
    83          200:
    84            description: list the todo operations
    85            schema:
    86              type: array
    87              items:
    88                $ref: "#/definitions/item"
    89  ```
    90  
    91  This snippet of yaml defines a `GET /` operation and tags it with _todos_. Tagging things is useful for many tools, for example helping UI tools group endpoints appropriately. Code generators might turn them into 'controllers'. There is also a response defined with a generic description about the response content. Note that some generators will put the description into the http status message. The response also defines endpoint's return type. In this case the endpoint returns a list of todo items, so the schema is an _array_ and the array will contain `item` objects, which you defined previously.
    92  
    93  But wait a minute, what if there are 100's of todo items, will we just return all of them for everybody?  It would be good to add a `since` and `limit` param here. The ids will have to be ordered for a `since` param to work but you're in control of that so that's fine.
    94  
    95  ```yaml
    96  ---
    97  paths:
    98    /:
    99      get:
   100        tags:
   101          - todos
   102        parameters:
   103          - name: since
   104            in: query
   105            type: integer
   106            format: int64
   107          - name: limit
   108            in: query
   109            type: integer
   110            format: int32
   111            default: 20
   112        responses:
   113          200:
   114            description: list the todo operations
   115            schema:
   116              type: array
   117              items:
   118                $ref: "#/definitions/item"
   119  ```
   120  
   121  With this new version of the operation you now have query params. These parameters have defaults so users can leave them off and the API will still function as intended.
   122  
   123  However, this definition is extremely optimistic and only defines a response for the "happy path". It's very likely that the API will need to return errors too. That means you have to define a model errors, as well as at least one more response definition to cover the error response.
   124  
   125  The error definition looks like this:
   126  
   127  ```yaml
   128  ---
   129  definitions:
   130    error:
   131      type: object
   132      required:
   133        - message
   134      properties:
   135        code:
   136          type: integer
   137          format: int64
   138        message:
   139          type: string
   140  ```
   141  
   142  For the error response you can use the default response, on the assumption that every successful response from your API is defying the odds.
   143  
   144  ```yaml
   145  ---
   146  paths:
   147    /:
   148      get:
   149        tags:
   150          - todos
   151        parameters:
   152          - name: since
   153            in: query
   154            type: integer
   155            format: int64
   156          - name: limit
   157            in: query
   158            type: integer
   159            format: int32
   160            default: 20
   161        responses:
   162          200:
   163            description: list the todo operations
   164            schema:
   165              type: array
   166              items:
   167                $ref: "#/definitions/item"
   168          default:
   169            description: generic error response
   170            schema:
   171              $ref: "#/definitions/error"
   172  ```
   173  
   174  At this point you've defined your first endpoint completely. To improve the strength of this contract you could define responses for each of the status codes and perhaps return different error messages for different statuses. For now, the status code will be provided in the error message.
   175  
   176  Try validating the specification again with `swagger validate ./swagger.yml` to ensure that code generation will work as expected. Generating code from an invalid specification leads to unpredictable results.
   177  
   178  Your completed spec should look like this:
   179  
   180  ```yaml
   181  ---
   182  swagger: "2.0"
   183  info:
   184    description: From the todo list tutorial on goswagger.io
   185    title: A Todo list application
   186    version: 1.0.0
   187  consumes:
   188  - application/io.goswagger.examples.todo-list.v1+json
   189  produces:
   190  - application/io.goswagger.examples.todo-list.v1+json
   191  schemes:
   192  - http
   193  paths:
   194    /:
   195      get:
   196        tags:
   197          - todos
   198        parameters:
   199          - name: since
   200            in: query
   201            type: integer
   202            format: int64
   203          - name: limit
   204            in: query
   205            type: integer
   206            format: int32
   207            default: 20
   208        responses:
   209          200:
   210            description: list the todo operations
   211            schema:
   212              type: array
   213              items:
   214                $ref: "#/definitions/item"
   215          default:
   216            description: generic error response
   217            schema:
   218              $ref: "#/definitions/error"
   219  definitions:
   220    item:
   221      type: object
   222      required:
   223        - description
   224      properties:
   225        id:
   226          type: integer
   227          format: int64
   228          readOnly: true
   229        description:
   230          type: string
   231          minLength: 1
   232        completed:
   233          type: boolean
   234    error:
   235      type: object
   236      required:
   237        - message
   238      properties:
   239        code:
   240          type: integer
   241          format: int64
   242        message:
   243          type: string
   244  ```
   245  
   246  When you generate a server for this spec you'll see the following output:
   247  
   248  ```
   249  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-1
   250  git:(master) ✗ !? » swagger generate server -A todo-list -f ./swagger.yml
   251  2018/01/06 11:49:16 building a plan for generation
   252  2018/01/06 11:49:16 planning definitions
   253  2018/01/06 11:49:16 planning operations
   254  2018/01/06 11:49:16 grouping operations into packages
   255  2018/01/06 11:49:16 planning meta data and facades
   256  2018/01/06 11:49:16 rendering 3 models
   257  2018/01/06 11:49:16 rendering 1 templates for model getOKBody
   258  2018/01/06 11:49:16 name field getOKBody
   259  2018/01/06 11:49:16 package field models
   260  2018/01/06 11:49:16 creating generated file "get_okbody.go" in "models" as definition
   261  2018/01/06 11:49:16 executed template asset:model
   262  2018/01/06 11:49:16 rendering 1 templates for model item
   263  2018/01/06 11:49:16 name field item
   264  2018/01/06 11:49:16 package field models
   265  2018/01/06 11:49:16 creating generated file "item.go" in "models" as definition
   266  2018/01/06 11:49:16 executed template asset:model
   267  2018/01/06 11:49:16 rendering 1 templates for model error
   268  2018/01/06 11:49:16 name field error
   269  2018/01/06 11:49:16 package field models
   270  2018/01/06 11:49:16 creating generated file "error.go" in "models" as definition
   271  2018/01/06 11:49:16 executed template asset:model
   272  2018/01/06 11:49:16 rendering 1 operation groups (tags)
   273  2018/01/06 11:49:16 rendering 1 operations for todos
   274  2018/01/06 11:49:16 rendering 4 templates for operation todo-list
   275  2018/01/06 11:49:16 name field Get
   276  2018/01/06 11:49:16 package field todos
   277  2018/01/06 11:49:16 creating generated file "get_parameters.go" in "restapi/operations/todos" as parameters
   278  2018/01/06 11:49:16 executed template asset:serverParameter
   279  2018/01/06 11:49:16 name field Get
   280  2018/01/06 11:49:16 package field todos
   281  2018/01/06 11:49:16 creating generated file "get_urlbuilder.go" in "restapi/operations/todos" as urlbuilder
   282  2018/01/06 11:49:16 executed template asset:serverUrlbuilder
   283  2018/01/06 11:49:16 name field Get
   284  2018/01/06 11:49:16 package field todos
   285  2018/01/06 11:49:16 creating generated file "get_responses.go" in "restapi/operations/todos" as responses
   286  2018/01/06 11:49:16 executed template asset:serverResponses
   287  2018/01/06 11:49:16 name field Get
   288  2018/01/06 11:49:16 package field todos
   289  2018/01/06 11:49:16 creating generated file "get.go" in "restapi/operations/todos" as handler
   290  2018/01/06 11:49:16 executed template asset:serverOperation
   291  2018/01/06 11:49:16 rendering 0 templates for operation group todo-list
   292  2018/01/06 11:49:16 rendering support
   293  2018/01/06 11:49:16 rendering 6 templates for application TodoList
   294  2018/01/06 11:49:16 name field TodoList
   295  2018/01/06 11:49:16 package field operations
   296  2018/01/06 11:49:16 creating generated file "configure_todo_list.go" in "restapi" as configure
   297  2018/01/06 11:49:16 executed template asset:serverConfigureapi
   298  2018/01/06 11:49:16 name field TodoList
   299  2018/01/06 11:49:16 package field operations
   300  2018/01/06 11:49:16 creating generated file "main.go" in "cmd/todo-list-server" as main
   301  2018/01/06 11:49:16 executed template asset:serverMain
   302  2018/01/06 11:49:16 name field TodoList
   303  2018/01/06 11:49:16 package field operations
   304  2018/01/06 11:49:16 creating generated file "embedded_spec.go" in "restapi" as embedded_spec
   305  2018/01/06 11:49:16 executed template asset:swaggerJsonEmbed
   306  2018/01/06 11:49:16 name field TodoList
   307  2018/01/06 11:49:16 package field operations
   308  2018/01/06 11:49:16 creating generated file "server.go" in "restapi" as server
   309  2018/01/06 11:49:16 executed template asset:serverServer
   310  2018/01/06 11:49:16 name field TodoList
   311  2018/01/06 11:49:16 package field operations
   312  2018/01/06 11:49:16 creating generated file "todo_list_api.go" in "restapi/operations" as builder
   313  2018/01/06 11:49:16 executed template asset:serverBuilder
   314  2018/01/06 11:49:16 name field TodoList
   315  2018/01/06 11:49:16 package field operations
   316  2018/01/06 11:49:16 creating generated file "doc.go" in "restapi" as doc
   317  2018/01/06 11:49:16 executed template asset:serverDoc
   318  2018/01/06 11:49:16 Generation completed!
   319  
   320  For this generation to compile you need to have some packages in your GOPATH:
   321  
   322    * github.com/go-openapi/runtime
   323    * github.com/jessevdk/go-flags
   324  
   325  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-1
   326  git:(master) ✗ !? » tree
   327  .
   328  ├── cmd
   329  │   └── todo-list-server
   330  │       └── main.go
   331  ├── models
   332  │   ├── error.go
   333  │   ├── get_okbody.go
   334  │   └── item.go
   335  ├── restapi
   336  │   ├── configure_todo_list.go
   337  │   ├── doc.go
   338  │   ├── embedded_spec.go
   339  │   ├── operations
   340  │   │   ├── todo_list_api.go
   341  │   │   └── todos
   342  │   │       ├── get.go
   343  │   │       ├── get_parameters.go
   344  │   │       ├── get_responses.go
   345  │   │       └── get_urlbuilder.go
   346  │   └── server.go
   347  └── swagger.yml
   348  
   349  6 directories, 14 files
   350  ```
   351  
   352  In this file tree you see that there is a `cmd/todo-list-server` directory. The swagger generator adds "-server" to the application name that you gave via the `-A` argument.
   353  
   354  The next section in this tree is the `models` package. This package contains go representations for all item definitions in the swagger spec document.
   355  
   356  The last section is `restapi`. The `restapi` package is generated based on the `paths` property in the swagger specification. The go swagger generator uses tags to group the operations into packages.
   357  
   358  You can also name operation by specifying an `operationId` in the specification for a path:
   359  
   360  
   361  ```yaml
   362  ---
   363  paths:
   364    /:
   365      get:
   366        tags:
   367          - todos
   368        operationId: find_todos
   369        ...
   370  ```
   371  
   372  These `operationId` values are used to name the generated files:
   373  
   374  ```
   375  .
   376  ├── cmd
   377  │   └── todo-list-server
   378  │       └── main.go
   379  ├── models
   380  │   ├── error.go
   381  │   ├── find_todos_okbody.go
   382  │   ├── get_okbody.go
   383  │   └── item.go
   384  ├── restapi
   385  │   ├── configure_todo_list.go
   386  │   ├── doc.go
   387  │   ├── embedded_spec.go
   388  │   ├── operations
   389  │   │   ├── todo_list_api.go
   390  │   │   └── todos
   391  │   │       ├── find_todos.go
   392  │   │       ├── find_todos_parameters.go
   393  │   │       ├── find_todos_responses.go
   394  │   │       └── find_todos_urlbuilder.go
   395  │   └── server.go
   396  └── swagger.yml
   397  ```
   398  
   399  You can see that the files under `restapi/operations/todos` now use the `operationId` as part of the generated file names.
   400  
   401  At this point can start the server, but first let's see what `--help` gives you. First install the server binary and then run it:
   402  
   403  ```
   404  ± ~/go/src/.../examples/tutorials/todo-list/server-1
   405  » go install ./cmd/todo-list-server/
   406  ± ~/go/src/.../examples/tutorials/todo-list/server-1
   407  » todo-list-server --help
   408  Usage:
   409    todo-list-server [OPTIONS]
   410  
   411  From the todo list tutorial on goswagger.io
   412  
   413  Application Options:
   414        --scheme=            the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec
   415        --cleanup-timeout=   grace period for which to wait before shutting down the server (default: 10s)
   416        --max-header-size=   controls the maximum number of bytes the server will read parsing the request header's keys and values, including the
   417                             request line. It does not limit the size of the request body. (default: 1MiB)
   418        --socket-path=       the unix socket to listen on (default: /var/run/todo-list.sock)
   419        --host=              the IP to listen on (default: localhost) [$HOST]
   420        --port=              the port to listen on for insecure connections, defaults to a random value [$PORT]
   421        --listen-limit=      limit the number of outstanding requests
   422        --keep-alive=        sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)
   423                             (default: 3m)
   424        --read-timeout=      maximum duration before timing out read of the request (default: 30s)
   425        --write-timeout=     maximum duration before timing out write of the response (default: 60s)
   426        --tls-host=          the IP to listen on for tls, when not specified it's the same as --host [$TLS_HOST]
   427        --tls-port=          the port to listen on for secure connections, defaults to a random value [$TLS_PORT]
   428        --tls-certificate=   the certificate to use for secure connections [$TLS_CERTIFICATE]
   429        --tls-key=           the private key to use for secure connections [$TLS_PRIVATE_KEY]
   430        --tls-ca=            the certificate authority file to be used with mutual tls auth [$TLS_CA_CERTIFICATE]
   431        --tls-listen-limit=  limit the number of outstanding requests
   432        --tls-keep-alive=    sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)
   433        --tls-read-timeout=  maximum duration before timing out read of the request
   434        --tls-write-timeout= maximum duration before timing out write of the response
   435  
   436  Help Options:
   437    -h, --help               Show this help message
   438  ```
   439  
   440  If you run your application now it will start on a random port by default. This might not be what you want, so you can configure a port through a command line argument or a `PORT` env var.
   441  
   442  ```
   443  git:(master) ✗ !? » todo-list-server
   444  serving todo list at http://127.0.0.1:64637
   445  ```
   446  
   447  You can use `curl` to check your API:
   448  
   449  ```
   450  git:(master) ✗ !? » curl -i http://127.0.0.1:64637/
   451  ```
   452  ```http
   453  HTTP/1.1 501 Not Implemented
   454  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   455  Date: Thu, 31 Dec 2015 22:42:10 GMT
   456  Content-Length: 57
   457  
   458  "operation todos.FindTodos has not yet been implemented"
   459  ```
   460  
   461  As you can see, the generated API isn't very usable yet, but we know it runs and does something. To make it useful you'll need to implement the actual logic behind those endpoints. And you'll also want to add some more endpoints, like adding a new todo item and updating an existing item to change its description or mark it completed.
   462  
   463  To supporting  adding a todo item you should define a `POST` operation:
   464  
   465  ```yaml
   466  ---
   467  paths:
   468    /:
   469      post:
   470        tags:
   471          - todos
   472        operationId: addOne
   473        parameters:
   474          - name: body
   475            in: body
   476            schema:
   477              $ref: "#/definitions/item"
   478        responses:
   479          201:
   480            description: Created
   481            schema:
   482              $ref: "#/definitions/item"
   483          default:
   484            description: error
   485            schema:
   486              $ref: "#/definitions/error"
   487  ```
   488  
   489  This snippet has something new. You see that the parameters are defined using a `schema` that references our exist item model. Remember that we defined this object's `id` key as _readOnly_, so it will not be accepted as part of the `POST` body.
   490  
   491  Next you can define a `DELETE` to remove a todo item from the list:
   492  
   493  ```yaml
   494  ---
   495  paths:
   496    /{id}:
   497      delete:
   498        tags:
   499          - todos
   500        operationId: destroyOne
   501        parameters:
   502          - type: integer
   503            format: int64
   504            name: id
   505            in: path
   506            required: true
   507        responses:
   508          204:
   509            description: Deleted
   510          default:
   511            description: error
   512            schema:
   513              $ref: "#/definitions/error"
   514  ```
   515  
   516  This time you're defining a parameter that is part of the `path`. This operation will look in the URI templated path for an id. Since there's nothing to return after a delete, the success response  is `204 No Content`.
   517  
   518  Finally, you need to define a way to update an existing item:
   519  
   520  ```yaml
   521  ---
   522  paths:
   523    /{id}:
   524      parameters:
   525        - type: integer
   526          format: int64
   527          name: id
   528          in: path
   529          required: true
   530      put:
   531        tags: ["todos"]
   532        operationId: updateOne
   533        parameters:
   534          - name: body
   535            in: body
   536            schema:
   537              $ref: "#/definitions/item"
   538        responses:
   539          '200':
   540            description: OK
   541            schema:
   542              $ref: "#/definitions/item"
   543          default:
   544            description: error
   545            schema:
   546              $ref: "#/definitions/error"
   547      delete:
   548        # elided for brevity
   549  ```
   550  
   551  There are two approaches typically taken for updates. A `PUT` indicates that the entire entity is being replaced, and a `PATCH` indicates that only the fields provided in the request should be updated. In the above example, you can see that the `PUT` "brute force" approach is being used.
   552  
   553  Another thing to note is that because the `/{id}` path is shared for both `DELETE` and `PUT`, they can share a `parameters` definition.
   554  
   555  At this point you should have a complete specification for the todo list API:
   556  
   557  ```yaml
   558  ---
   559  swagger: "2.0"
   560  info:
   561    description: From the todo list tutorial on goswagger.io
   562    title: A Todo list application
   563    version: 1.0.0
   564  consumes:
   565  - application/io.goswagger.examples.todo-list.v1+json
   566  produces:
   567  - application/io.goswagger.examples.todo-list.v1+json
   568  schemes:
   569  - http
   570  - https
   571  paths:
   572    /:
   573      get:
   574        tags:
   575          - todos
   576        operationId: findTodos
   577        parameters:
   578          - name: since
   579            in: query
   580            type: integer
   581            format: int64
   582          - name: limit
   583            in: query
   584            type: integer
   585            format: int32
   586            default: 20
   587        responses:
   588          200:
   589            description: list the todo operations
   590            schema:
   591              type: array
   592              items:
   593                $ref: "#/definitions/item"
   594          default:
   595            description: generic error response
   596            schema:
   597              $ref: "#/definitions/error"
   598      post:
   599        tags:
   600          - todos
   601        operationId: addOne
   602        parameters:
   603          - name: body
   604            in: body
   605            schema:
   606              $ref: "#/definitions/item"
   607        responses:
   608          201:
   609            description: Created
   610            schema:
   611              $ref: "#/definitions/item"
   612          default:
   613            description: error
   614            schema:
   615              $ref: "#/definitions/error"
   616    /{id}:
   617      parameters:
   618        - type: integer
   619          format: int64
   620          name: id
   621          in: path
   622          required: true
   623      put:
   624        tags:
   625          - todos
   626        operationId: updateOne
   627        parameters:
   628          - name: body
   629            in: body
   630            schema:
   631              $ref: "#/definitions/item"
   632        responses:
   633          200:
   634            description: OK
   635            schema:
   636              $ref: "#/definitions/item"
   637          default:
   638            description: error
   639            schema:
   640              $ref: "#/definitions/error"
   641      delete:
   642        tags:
   643          - todos
   644        operationId: destroyOne
   645        responses:
   646          204:
   647            description: Deleted
   648          default:
   649            description: error
   650            schema:
   651              $ref: "#/definitions/error"
   652  definitions:
   653    item:
   654      type: object
   655      required:
   656        - description
   657      properties:
   658        id:
   659          type: integer
   660          format: int64
   661          readOnly: true
   662        description:
   663          type: string
   664          minLength: 1
   665        completed:
   666          type: boolean
   667    error:
   668      type: object
   669      required:
   670        - message
   671      properties:
   672        code:
   673          type: integer
   674          format: int64
   675        message:
   676          type: string
   677  ```
   678  
   679  This is a good time to sanity check and by validating the schema:
   680  
   681  ```
   682  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-2
   683  git:(master) ✗ !? » swagger validate ./swagger.yml
   684  The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
   685  ```
   686  
   687  Now you're ready to generate the API and start filling in the actual operations:
   688  
   689  ```
   690  git:(master) ✗ !? » swagger generate server -A TodoList -f ./swagger.yml
   691  ... elided output ...
   692  2015/12/31 18:16:28 rendered main template: server.TodoList
   693  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-2
   694  git:(master) ✗ !? » tree
   695  .
   696  ├── cmd
   697  │   └── todo-list-server
   698  │       └── main.go
   699  ├── models
   700  │   ├── error.go
   701  │   ├── find_todos_okbody.go
   702  │   └── item.go
   703  ├── restapi
   704  │   ├── configure_todo_list.go
   705  │   ├── doc.go
   706  │   ├── embedded_spec.go
   707  │   ├── operations
   708  │   │   ├── todo_list_api.go
   709  │   │   └── todos
   710  │   │       ├── add_one.go
   711  │   │       ├── add_one_parameters.go
   712  │   │       ├── add_one_responses.go
   713  │   │       ├── add_one_urlbuilder.go
   714  │   │       ├── destroy_one.go
   715  │   │       ├── destroy_one_parameters.go
   716  │   │       ├── destroy_one_responses.go
   717  │   │       ├── destroy_one_urlbuilder.go
   718  │   │       ├── find_todos.go
   719  │   │       ├── find_todos_parameters.go
   720  │   │       ├── find_todos_responses.go
   721  │   │       ├── find_todos_urlbuilder.go
   722  │   │       ├── update_one.go
   723  │   │       ├── update_one_parameters.go
   724  │   │       ├── update_one_responses.go
   725  │   │       └── update_one_urlbuilder.go
   726  │   └── server.go
   727  └── swagger.yml
   728  
   729  6 directories, 26 files
   730  ```
   731  
   732  To implement the core of your application you start by editing `restapi/configure_todo_list.go`. This file is safe to edit. Its content will not be overwritten if you run `swagger generate` again the future.
   733  
   734  The simplest way to implement this application is to simply store all the todo items in a golang `map`. This provides a simple way to move forward without bringing in complications like a database or files.
   735  
   736  To do this you'll need a map and a counter to track the last assigned id:
   737  
   738  ```go
   739  // the variables we need throughout our implementation
   740  var items = make(map[int64]*models.Item)
   741  var lastID int64
   742  ```
   743  
   744  The simplest handler to implement now is the delete handler. Because the store is a map and the id of the item is provided in the request it's a one liner.
   745  
   746  ```go
   747  api.TodosDestroyOneHandler = todos.DestroyOneHandlerFunc(func(params todos.DestroyOneParams) middleware.Responder {
   748    delete(items, params.ID)
   749    return todos.NewDestroyOneNoContent()
   750  })
   751  ```
   752  
   753  After deleting the item from the store, you need to provide a response. The code generator created responders for each response you defined in the the swagger specification, and you can see how one of those is being used in the example above.
   754  
   755  The other 3 handler implementations are similar to this one. They are provided in the [source for this tutorial](https://github.com/go-swagger/go-swagger/blob/master/examples/tutorials/todo-list/server-complete/restapi/configure_todo_list.go).
   756  
   757  So assuming you go ahead and implement the remainder of the endpoints, you're all set to test it out:
   758  
   759  ```
   760  » curl -i localhost:8765
   761  ```
   762  ```http
   763  HTTP/1.1 200 OK
   764  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   765  Date: Fri, 01 Jan 2016 19:56:01 GMT
   766  Content-Length: 3
   767  
   768  []
   769  ```
   770  ```
   771  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   772  ```
   773  ```http
   774  » curl -i localhost:8765 -d "{\"description\":\"message $RANDOM\"}"
   775  HTTP/1.1 415 Unsupported Media Type
   776  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   777  Date: Fri, 01 Jan 2016 19:56:11 GMT
   778  Content-Length: 157
   779  
   780  {"code":415,"message":"unsupported media type \"application/x-www-form-urlencoded\", only [application/io.goswagger.examples.todo-list.v1+json] are allowed"}                                                                                                     ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   781  ```
   782  ```
   783  » curl -i localhost:8765 -d "{\"description\":\"message $RANDOM\"}" -H 'Content-Type: application/io.goswagger.examples.todo-list.v1+json'
   784  ```
   785  ```http
   786  HTTP/1.1 201 Created
   787  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   788  Date: Fri, 01 Jan 2016 19:56:20 GMT
   789  Content-Length: 39
   790  
   791  {"description":"message 30925","id":1}
   792  ```
   793  ```
   794  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   795  » curl -i localhost:8765 -d "{\"description\":\"message $RANDOM\"}" -H 'Content-Type: application/io.goswagger.examples.todo-list.v1+json'
   796  ```
   797  ```http
   798  HTTP/1.1 201 Created
   799  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   800  Date: Fri, 01 Jan 2016 19:56:23 GMT
   801  Content-Length: 37
   802  
   803  {"description":"message 104","id":2}
   804  ```
   805  ```
   806  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   807  » curl -i localhost:8765 -d "{\"description\":\"message $RANDOM\"}" -H 'Content-Type: application/io.goswagger.examples.todo-list.v1+json'
   808  ```
   809  ```http
   810  HTTP/1.1 201 Created
   811  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   812  Date: Fri, 01 Jan 2016 19:56:24 GMT
   813  Content-Length: 39
   814  
   815  {"description":"message 15225","id":3}
   816  ```
   817  ```
   818  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   819  » curl -i localhost:8765
   820  ```
   821  ```http
   822  HTTP/1.1 200 OK
   823  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   824  Date: Fri, 01 Jan 2016 19:56:26 GMT
   825  Content-Length: 117
   826  
   827  [{"description":"message 30925","id":1},{"description":"message 104","id":2},{"description":"message 15225","id":3}]
   828  ```
   829  ```
   830  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   831  » curl -i localhost:8765/3 -X PUT -H 'Content-Type: application/io.goswagger.examples.todo-list.v1+json' -d '{"description":"go shopping"}'
   832  ```
   833  ```http
   834  HTTP/1.1 200 OK
   835  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   836  Date: Fri, 01 Jan 2016 19:56:32 GMT
   837  Content-Length: 37
   838  
   839  {"description":"go shopping","id":3}
   840  ```
   841  ```
   842  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   843  » curl -i localhost:8765
   844  ```
   845  ```http
   846  HTTP/1.1 200 OK
   847  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   848  Date: Fri, 01 Jan 2016 19:56:34 GMT
   849  Content-Length: 115
   850  
   851  [{"description":"message 30925","id":1},{"description":"message 104","id":2},{"description":"go shopping","id":3}]
   852  ```
   853  ```
   854  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   855  » curl -i localhost:8765/1 -X DELETE -H 'Content-Type: application/io.goswagger.examples.todo-list.v1+json'
   856  ```
   857  ```http
   858  HTTP/1.1 204 No Content
   859  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   860  Date: Fri, 01 Jan 2016 19:57:04 GMT
   861  ```
   862  ```
   863  ± ~/go/src/github.com/go-swagger/go-swagger/examples/tutorials/todo-list/server-complete
   864  » curl -i localhost:8765
   865  ```
   866  ```http
   867  HTTP/1.1 200 OK
   868  Content-Type: application/io.goswagger.examples.todo-list.v1+json
   869  Date: Fri, 01 Jan 2016 19:57:06 GMT
   870  Content-Length: 76
   871  
   872  [{"description":"message 104","id":2},{"description":"go shopping","id":3}]
   873  ```