Hacker News new | ask | show | jobs
by mpetrovich 1297 days ago
Making the version optional is a bad idea, IMO. It lets consumers use your API without versioning, which is like telling them, “here, create a time bomb that may or may not explode when the next breaking api change is released.”

There’s zero practical user benefit to NOT specifying the version, so why not enforce it? You’re creating a footgun otherwise.

Furthermore as others have pointed out, this is a purely cosmetic change. Using /api/$UNIQUE_STR in the URL vs. X-GitHub-Version: $UNIQUE_STR in the header are functionally equivalent, so…

Why bother making this change then? What was suboptimal about the previous way? What benefit does this bring?

EDIT: Serves me right for not reading the docs more carefully. From the docs [1]:

Requests without the X-GitHub-Api-Version header will default to use the 2022-11-28 version.

See phphphphp’s reply below for context.

[1] https://docs.github.com/en/rest/overview/api-versions?apiVer...

4 comments

The version is only optional in the request: when it isn’t provided in the request then the system will default to the version of the API that would have been given had this new system not been implemented, so there is no change in behaviour for existing implementations, there are no footguns or impending explosions. The key point is when they refer to today, they don’t mean “today as of the time of the request” they mean today, as a point in time: November 28th, 2022.

The benefit of this new versioning approach is that they can maintain backwards compatibility for existing implementations while introducing breaking changes for new implementations to benefit from.

In an ideal world, sure, they should have implemented this from the start, but they didn’t, so going forward they have to accommodate both existing implementations (by not breaking anything) and new implementations (by providing features that would break existing implementations).

They’re basically just implementing stripe’s well-understood and battle tested approach for versioning, while maintaining backwards compatibility. I am struggling to see any problems with the approach, in fact, it seems like the only right approach (?)

Oh, so you’re saying that omitting the version from the header will ALWAYS return this specific version, NOT the latest version?

That certainly addresses the footgun I mentioned.

EDIT: From the docs: Requests without the X-GitHub-Api-Version header will default to use the 2022-11-28 version.

Yes, exactly, that’s my understanding from the blog post and changelog post. I think perhaps the waters have been muddied a little because of our expectations of API versioning + GitHub’s need to maintain backwards compatibility for existing implementations. The way I understand is that “v3” of the API (which has been around for 10 years) is now version “2022-11-28” and so existing implementations while be using version “2022-11-28” without any required change.
I don't see how that can be true when new versions put a 2y time bomb on old versions.

At some point the default 28th Nov 2022 version is unsupported... So what is served must change... Either it's the latest at the time or the behaviour of receiving a response without providing the header is removed.

I often find it useful to think of things like this as "no version specified" being the lowest version, and then explicit versions start counting after that.
Author here. You've put it better than I could have put it myself. Thanks!
Because they use calendar versioning the user benefit to not specifying is not having to keep track of a million different dates.

I work with a lot of APIs that just have “/v1” or “/v2” as part of the endpoint so it’s easy to specify. Setting a header parameter to a specific date is a PITA and I certainly don’t want to look up the curl syntax whenever I do simple work.

I think if they made it required, it would annoy people. So they didn’t.

I agree with you, so then why not stick with the previous /api/v2 url approach?

And it would annoy me far more if my app that talks to GitHub inexplicably breaks in a few years because of a release I wasn’t aware of.

These changes make no sense to me.

It enforces the idea that the API is versioned per endpoint and not overall.

You can update each endpoint in non-backwards compatible ways without having to update all of them.

If you have it in the URL, it's likely libraries and custom scripts will just set the value in configuration instead of per-callsite.

You don't want to have to wait to fix up some API or make non-updates on all the rest just to release a new version.

edit: I agree that making it optional is a bad move

You’re saying that it’s LESS likely to specify the API path at the callsite than the HTTP header? o_O
I was saying that having /v2/ in the URL implies all of the endpoints will have a /v2/ and that they will be part of a matched set. Having it in the header makes for having version numbers that are targeted at each specific endpoint without making it look like the others are affected.

Here specifically I was suggesting that the /v2/ in the URL would make people using the API more likely to set the /v2/ in their app to use it across all calls rather than different per endpoint versions.

It looks like the calls are in the version rather than the version being in the calls.

I don't see the difference. For this call I'm using the v2 API. For this one the v3. It's much harder to wrangle headers than to do this, IMO.
In reality it's probably completely equivalent. The version prefix in the path would probably live in some GITHUB_API_URL variable. The header would be set on the http session object.
>> Setting a header parameter to a specific date is a PITA

Really? Don't you do this all the time for everything beyond a simple GET? From my experience it's far preferable than URL versioning because you can version on an individual endpoint. Right now I'm consuming Versions 0.9, 1.0 and 2.0 from a vendor; it would be way nicer to set individual headers than somehow mananging multiple endpoints.

I’m not saying that it’s difficult, just that it’s a pain in the rear end. You can’t cut and paste calls, you have to have two variables to see the version. It’s just minor annoyances.

That being said, I don’t call multiple versions of an api so maybe it’s nice to just be able to call multiples.

I imagine that it’s pretty easy to manage with the url version as you’re still just storing one endpoint and appending the version depending on what you would like. So programmatically you just change a config variable with the version you want.

But it seems like the version on changes with breaks so if you’re calling different versions you have to handle the input and output differently anyway.

> it would be way nicer to set individual headers than somehow mananging multiple endpoints

I don't understand the difference. What makes it nicer?

Is there an easy way to set a ‘sticky’ curl header, or change/set the default headers?

I did a quick search and couldn’t see any docs on this use case.

Behold the power of curlrc: https://curl.se/docs/manpage.html#-K

And it behaves the same way as `curl --header "" --header ""` in that it's additive:

    $ curl -vK <(printf 'header = "alpha: 1"\nheader = "beta: 2"\n') httpbin.org/get
Why version at all? They went 10 years without versioning. The reasons stated for needing versioning are weak at best ("like deleting a response field, making an optional parameter required, or deleting an endpoint entirely"). Just retain backwards compatibility. Once you have versioning, people feel more comfortable making incompatible updates which is a terrible direction.
> Just retain backwards compatibility.

I'll take the bait, like C++?

> comfortable making incompatible updates

Incompatible how? You specify the version, your semantics are of that version.

Until github removes that version, which they will:

> When a new REST API version is released, we’re committed to supporting the previous version for at least two years (24 months).

I think that's an interesting question here. Especially with how much was invested into GitHub's GraphQL and the once implication that the GraphQL API would entirely replace the REST API. (And the GraphQL API still having its own, different versioning scheme now and after the change mentioned in this blog post.)

The blog post suggests that we might find out some of the API changes that warranted this change as early as next month, but it would have been great for this blog post to include some examples of changes that were coming.

You could make the argument that having it in the URL is better than using a custom header, because customer headers may see mangling/blocking in corporate environments (indiscriminantly).

I don't think it's a strong point.