Most APIs are versioned using a version prefix like /v1.0/
, /v2/
etc. In theory, every major API change should increase the major version number, to maintain backward compatibility with clients consuming the API. This quickly becomes problematic if the API wants to evolve quickly, the URLs would have to be updated often.
A more elegant solution to solve the backward compatibility issue is to tell a client to send, in a HTTP header with each request, the maximum version of the API it supports. The server is in charge of returning a response that is valid with respect to what the client understands. That technique is called content negotiation
.
The basic idea is to decorate each view function
(i.e the function in charge of a Flask endpoint) with a decorator that tells for which version of the API a view function
is available.
To indicate that an endpoint is only available to clients which send a X-Version
HTTP header between 1.0 and 1.1, do:
@app.api_version(
min_ver="1.0,
max_ver="1.1"
)
@app.route('/ep1')
def index():
return b'ep1'
To deprecate an endpoint, just decorate it with api_version
and a max_ver
argument. To introduce an endpoint, hidden to old client, just decorate it with api_version
and a min_ver
argument. Finally, to serve different content based on which version a client understands, do:
@app.route('/versioned_view')
def index():
requested_version = flask.g.api_version_request
if requested_version.matches("1.2"):
return b'1.2'
elif requested_version.matches("1.1"):
return b'1.1'
else:
return b'1.0'
The code, especially the api_version_request
and versioned_method
modules, is heavily borrowed from the OpenStack project.