The second thing I've been reading about this week is OpenAPI, a way of specifying REST APIs. Well, a way of specifying the API for a server that defines its actions in terms of well-known endpoints and HTTP verbs like GET, PUT, POST, and DELETE. (As well as HEAD, OPTIONS, PATCH, but presumably not the 32 others that Microsoft tried to burden us with for WebDAV.)

Since we've been using Go, we've been using GoSwagger, a tool for building web server frameworks with OpenAPI. OpenAPI defines a document, usually written in JSON or YAML, that defines a client, a server, or both, and the API that will be used to communicate between them.

The basic OpenAPI file has a header with some versioning and metadata information, as well as the scheme used, which is almost always HTTP (although I understand Websockets can be used here instead). After that, there are two sections:

paths: describes the URL that the user will follow to get to a resource, followed by a verb (get, put, post, delete), followed by paramaters (either in the body or in the CGI arguments), as well as the function name that will handle the transaction.

definitions: contains a collection of named objects, each with a JSON schema, that describes the payloads. You refer to these named objects in the paths: section, thus creating a relationship between the target and the schema.

A really simple one might just be "time of day" as a string, and takes the timezone as a single argument:

<code>swagger: "2.0"
info:
  title: clock
basePath: /clock/v1
produces: ["application/json"]

paths:
  /time:
    get:
      operationId: "time"
    parameters:
      - in: "path"
        name: "timezone"
        required: false
        type: "string"
    responses:
      200:
        schema:
          type: "string"
      500:
        schema:
          type: "string"</code>

Go's most common implementation of swagger, go-swagger, automatically generates a web server for you based on this definition. Your only responsibility is to find the file configure_clock.go, find the function time(), and fill in the details. You get the parameters as a map, with their types completely filled out, and go-swagger will enforce requirements like the timezone passed in be a string. It could be a string of anything; you'll still have to validate that it parses to a valid timezone.

OpenAPI is really nifty: It locks down "what you mean" about verbs and objects at the HTTP/JSON layer. It is not REST. REST requires more discipline than this. OpenAPI makes that discipline fairly easy, but the developer still has to know and use it. OpenAPI does not in anyway at all enforce the "coarse-grained document handling" that was introduced by Leonard Richardson, and it's completely possible that many developers will be introducing SOAP-like commands using HTTP verbs.

I do like how expressive Go is, at least at the simple level of "I want to do something." I really dislike how verbose Go is, especially when you're trying to do anything that might have a lot of side effects. It's an ugly language, and I'm never going to enjoy working in it fully. But it's easy to get good at it, so I guess I'm going to be good at it.