Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

versioning: in URL or in HTTP header? #1

Closed
pvdbosch opened this issue Jan 6, 2020 · 6 comments
Closed

versioning: in URL or in HTTP header? #1

pvdbosch opened this issue Jan 6, 2020 · 6 comments
Assignees

Comments

@pvdbosch
Copy link
Contributor

pvdbosch commented Jan 6, 2020

In GitLab by @wsalembi on Feb 23, 2018, 08:52

Beslissen of versienummer wordt opgenomen in URL van de API (momenteel in styleguide) versus in HTTP-header.

eHealth:

  • URL: Minder REST based, doordat resource versie krijgt.
  • Anderzijds is versie in header minder makkelijk in gebruik voor testen.

KSZ: voorkeur in URL

  • Vrijheid om resource-structuur volledig te veranderen tussen major versies (al uit ervaring bvb bij regionalisatie – resource-entiteiten opgesplitst)
  • In principe: versienummer zeer zelden wijzigen
    • Vaak binnen eenzelfde major versie ook uitfasering toelaten (graduele migratie – beide oud & nieuw deelstructuur teruggeven tijdelijk, dan oud uitfaseren) of big-bang bij beperkt aantal klanten, met akkoord van klanten
    • Alleen nieuwe versienummers bij incompatibele versies van de API die parallel ondersteund worden
  • Verandering minor versie zou niet verandering bij klant moeten vereisen
  • Gemakkelijker om op te roepen (geen custom http header)
  • Wel moeilijker: onderhouden van links vanuit andere APIs

FOD Fin:

  • Nous plaçons la version dans le header, ce qui est plus simple à gérer dans notre infrastructure actuelle. Nous souhaitons continuer à procéder de cette manière

VAS:

  • Version in URL/Header to specify the major version of the API.
    We prefer to put the version in the URL because it is easier to manage (our RP will forward all requests to Openshift and Openshift I don't know if it can handle HEADERS for the dispatching).
    While the API structure (list of resources) are the same, we prefer to keep the same major version in the URL.
    If there is a major change in the API structure (reorganisation of the resources), we prefer to create a new major version. Both versions are deployed at the same time to allow the clients to migrate progressively to the new version.
    This kind of change should be very rare.
  • Version in the mediatype if needed to allow non-backward compatible changes in the resource representations.
    Example: application/json;version=1
@pvdbosch pvdbosch self-assigned this Jan 6, 2020
@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Feb 23, 2018, 09:27

assigned to @pvdbosch

@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Mar 19, 2018, 18:08

Versioning strategies

Global URI versioning

Major version in the path (e.g., /api/v1/companies) or in subdomain (e.g., api-v2.foo.com/companies)

  • less RESTful because URL has version and doesn’t identify uniquely the resource anymore
    • difficult to maintain hyperlinks from other APIs => if they’re updated to new version: breaking change
  • freedom to change resource structure completely in new version and review standards applied (e.g. evolution in error-handling guidelines), clean break from legacy
  • possible to route requests to different deployments of the application implementing old / new version

Media type versioning (header-based)

Return different resource version depending on ‘Accept’ header of request, e.g.

Accept: application/resource.v1+json
Accept: application/resource.v2+json
Or:
Accept: application/json;version=1

  • RESTful: URL identifying resource stays the same
  • less easy to specify in request (e.g. for testing)
  • OpenAPI 2.0 doesn’t support content negotiation, OpenAPI 3.0 does support it
  • Which version to return for request with “Accept: application/json”?
    • If new one: breaks backwards compatibility for existing clients
      => releasing new version would be blocked on existing clients migrating to use ‘Accept: application/resource.oldversion+json’
    • If old one: makes retrieving new version non-obvious => new clients may start to use old version
  • Should an API already define media type with version for each new resource from the start ?

API Evolution

Avoid versioning as long as possible. Add new fields to existing resource representations next to old properties. Mark old fields as deprecated, but keep supporting them during a transition period during which clients can switch to the new version.
In OpenAPI, set deprecated=true on each method / path element that will be deprecated OpenAPI 2.0 only allows you to define deprecation on this level (improved in OpenAPI 3.0).
Other deprecations:

  • Custom property ‘x-deprecated’?
  • Zalando: If deprecation should happen on a more fine-grained level (i.e. query parameter, payload etc.), the producer should set deprecated=true on the affected method / path element and add further explanation to the description section.

Other guidelines

  • clear communication of phasing out of deprecated (parts of the) API
  • We might standardize a deprecation warning http header in response

Warning: 299 - "Miscellaneous Persistent Warning" "The parameter x has been deprecated and will be removed by {date}."
Or custom header
-Deprecated: "The parameter x has been deprecated and will be removed by {date}."

  • Semantic versioning of OpenAPI specifications. Maybe with patch version optional
  • if there is no period when old and new version are supported in parallel, version number may be kept the same even though there are backwards-incompatible changes i.e. big bang release coordinated with (usually a limited number of) clients)

Conclusions

Media type versioning still leaves some unsolved issues and quite some cases may be solved with API Evolution.

Proposal:

  • Use API Evolution whenever possible
  • Global versioning when it is really needed to make major revisions.
    • Open issue: links to resources from other APIs

Reference material:

@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Mar 21, 2018, 09:54

Feedback Willem sent me by mail:

Bij SocSec gebeurt api versioning in de URI en maakt deel uit van het basePath vb. "basePath": "/nssoTask/v1"

API gateway 7.5.3 ondersteunt enkel deze mode (in 7.6 komt daar query-param based versioning bij, maar geen http header versioning)

Volgens de RESTafarians is geen versioning de beste aanpak, maar misschien niet realistisch. Via redirects en content negotitiation zou een API nooit geversioneerd hoeven te worden.
Versioning via HTTP header is misschien de meest elegante oplossing omdat de URI van resources dan wel stabiel blijven.

We hebben ook gedacht aan een verschil te maken tussen versioning van resources (URI) tov van versioning van representations (maar nog nooit in praktijk gebracht)

bv

GET /nationRegister/v1/persons/{inss}
Accept: application/vnd.person.v2+json

dus URI blijven langer stabiel, maar representations kunnen wel binnen een bepaalde van versie van een API evolueren. Dit mapt ook mooi op het @producers concept van JAX-RS

@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Apr 18, 2018, 18:01

Conclusions of last meeting were:

  • Use API Evolution
  • Global versioning when it is really needed to make major revisions.
  • Don't include Media type versioning: it still leaves some unsolved issues and quite some cases may be solved with API Evolution.

I added this to the styleguide. Included deprecation guidelines under API evolution

@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Apr 18, 2018, 18:01

closed

@pvdbosch
Copy link
Contributor Author

pvdbosch commented Jan 6, 2020

In GitLab by @pvdbosch on Apr 18, 2018, 18:11

mentioned in commit b97b982

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant