Third Party Developer Blog

Mar
11

ESI Best Practices: Generating Code With Underscore Routes

CCP Bartender | 2021-03-11 17:22

This blog post is part of a series of blogs examining best practices for ESI development. Each blog will be published on the 8th of each month during the journey towards XML API and CREST’s termination date. The legacy APIs will be terminated on May 8th, 2018, or earlier if metrics signal a trivial level of usage.


This blog explains best practices for autogenerating language specific clients from the ESI swagger spec. When generating code from one of the named routes (e.g. https://esi.evetech.net/latest/swagger.json), you may have noticed the resulting client library uses /latest as the version in all its URL calls.

You can see why if you look at this fragment of the swagger spec from the above URL:

{
  "basePath": "/latest",
  "host": "esi.evetech.net",
  "info": {
    "description": "An OpenAPI for EVE Online",
    "title": "EVE Swagger Interface",
    "version": "0.4.4.dev4"
  },
  "paths": {
    "/alliances/": {
      "get": {
        "description": "List all active player alliances\n\n---\n\nAlternate route: `/v1/alliances/`\n\nAlternate route: `/legacy/alliances/`\n\nAlternate route: `/dev/alliances/`\n\n\n---\n\nThis route is cached for up to 3600 seconds",
        {...}
      }
    }
  }
}

The basePath for all URL's is set to /latest at the top level, and inherited by all paths. From the given example, the route /latest/alliances/ is assembled. That's a problem, because if a route currently part of /latest is bumped from v2 to v3, the autogenerated library will start calling the new /latest and could encounter errors. The best practice for stability is to pin the versions of all routes from /latest at the time code is tested and generated.

That capability is available in the form of "underscore routes". You can call https://esi.evetech.net/_latest/swagger.json and get a modified copy of the swagger spec, in which the basePath has been converted to the root /, and each route has been converted to its full versioned path:

{
  "basePath": "/",
  "host": "esi.evetech.net",
  "info": {
    "description": "An OpenAPI for EVE Online",
    "title": "EVE Swagger Interface",
    "version": "0.4.4.dev4"
  },
  "paths": {
    "/v1/alliances/": {
      "get": {
        "description": "List all active player alliances\n\n---\n\nThis route is cached for up to 3600 seconds",
        {...}
      }
    }
  }
}

From this example, the route /v1/alliances/ is assembled. This modified spec will never contain more than one version of a resource/verb pair, and you will find similar specs available at _dev and _legacy. When autogenerating code for ESI, it is best practice to use the underscore routes as a swagger source, to ensure the versions are pinned.

When using this technique, deprecation of routes is identified by watching for warning headers in the response. When a versioned route is moved from latest to legacy, it will start returning the following headers, even on an authentication failure:

{
  "server": "nginx",
  "date": "Mon, 08 May 2017 15:25:26 GMT",
  {...},
  "warning": "199 - This endpoint has been updated.",
  {...}
}

More details on this can be found in our blog about using versioned routes.

~CCP Bartender

back