This tutorial walks you through a hypothetical project, building a todo list.
It uses a todo list because this is a well-understood application, so you can
focus on the go-swagger pieces. Here we build the server; when you’re done,
head to the client SDK tutorial to generate a typed client
against the same spec.
Info
You’ll need the swagger CLI on your PATH. See
goswagger.io for installation, and the
command reference for the full set of
generate options. The finished code for each stage of this tutorial lives under
tutorials/todo-list/
in the examples repository (server-1, server-2, server-complete).
To create your application start with swagger init:
swagger init spec \
--title "A Todo list application"\
--description "From the todo list tutorial on goswagger.io"\
--version 1.0.0 \
--scheme http \
--consumes application/io.goswagger.examples.todo-list.v1+json \
--produces application/io.goswagger.examples.todo-list.v1+json
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.
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.
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:
paths:
/:
get:
tags:
- todosparameters:
- name: sincein: querytype: integerformat: int64 - name: limitin: querytype: integerformat: int32default: 20responses:
200:
description: list the todo operationsschema:
type: arrayitems:
$ref: "#/definitions/item"
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.
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.
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.
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.
You can see that the files under restapi/operations/todos now use the operationId as part of the generated file names.
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:
ยฑ ~/go/src/.../examples/tutorials/todo-list/server-1
ยป go install ./cmd/todo-list-server/
ยฑ ~/go/src/.../examples/tutorials/todo-list/server-1
ยป todo-list-server --help
Usage:
todo-list-server [OPTIONS]From the todo list tutorial on goswagger.io
Application Options:
--scheme= the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec
--cleanup-timeout= grace period for which to wait before shutting down the server (default: 10s) --max-header-size= controls the maximum number of bytes the server will read parsing the request header's keys and values, including the
request line. It does not limit the size of the request body. (default: 1MiB)
--socket-path= the unix socket to listen on (default: /var/run/todo-list.sock)
--host= the IP to listen on (default: localhost) [$HOST]
--port= the port to listen on for insecure connections, defaults to a random value [$PORT]
--listen-limit= limit the number of outstanding requests
--keep-alive= sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)
(default: 3m)
--read-timeout= maximum duration before timing out read of the request (default: 30s)
--write-timeout= maximum duration before timing out write of the response (default: 60s)
--tls-host= the IP to listen on for tls, when not specified it's the same as --host [$TLS_HOST] --tls-port= the port to listen on for secure connections, defaults to a random value [$TLS_PORT] --tls-certificate= the certificate to use for secure connections [$TLS_CERTIFICATE] --tls-key= the private key to use for secure connections [$TLS_PRIVATE_KEY] --tls-ca= the certificate authority file to be used with mutual tls auth [$TLS_CA_CERTIFICATE] --tls-listen-limit= limit the number of outstanding requests
--tls-keep-alive= sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download) --tls-read-timeout= maximum duration before timing out read of the request
--tls-write-timeout= maximum duration before timing out write of the response
Help Options:
-h, --help Show this help message
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.
git:(master) โ !? ยป todo-list-server
serving todo list at http://127.0.0.1:64637
HTTP/1.1501Not ImplementedContent-Type:application/io.goswagger.examples.todo-list.v1+jsonDate:Thu, 31 Dec 2015 22:42:10 GMTContent-Length:57"operation todos.FindTodos has not yet been implemented"
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.
To supporting adding a todo item you should define a POST operation:
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.
Finally, you need to define a way to update an existing item:
This is a good time to sanity check and by validating the schema:
ยฑ ~/go/src/github.com/go-swagger/examples/tutorials/todo-list/server-2
git:(master) โ !? ยป swagger validate ./swagger.yml
The swagger spec at "./swagger.yml" is valid against swagger specification 2.0
Now you’re ready to generate the API and start filling in the actual operations:
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.
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.
To do this you’ll need a map and a counter to track the last assigned id:
// the variables we need throughout our implementationvaritems = make(map[int64]*models.Item)
varlastIDint64
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.
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 swagger specification, and you can see how one of those is being used in the example above.
The other 3 handler implementations are similar to this one. They are provided in the
source for this tutorial.
So assuming you go ahead and implement the remainder of the endpoints, you’re all set to test it out:
ยป curl -i localhost:8765
HTTP/1.1200OKContent-Type:application/io.goswagger.examples.todo-list.v1+jsonDate:Fri, 01 Jan 2016 19:56:01 GMTContent-Length:3[]
ยป curl -i localhost:8765 -d "{\"description\":\"message $RANDOM\"}"
HTTP/1.1415Unsupported Media TypeContent-Type:application/io.goswagger.examples.todo-list.v1+jsonDate:Fri, 01 Jan 2016 19:56:11 GMTContent-Length:157{"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/examples/tutorials/todo-list/server-complete