Open timothycrosley opened 8 years ago
Due the nature of semantic versioning, where every bugfix means a new patch version, you will likely end up with more distinct versions than currently. This means that developers must delete old endpoints from time to time. To make this task easier, I think it's essential to have hug compile a list of all existing versions and their corresponding endpoints.
Also you could make the usage even more explicit (and save some keystrokes) by introducing a semver
type:
@hug.get(versions=hug.semver(3, 2))
def endpoint():
pass
This is something you would literally never want to use if your API faced the public Internet, right?
@nugend could you elaborate on that please?
Because you can't retire parts of the API or change functionality if you later discover that there is a bug or security issue and still maintain the semantic guarantee implied by the version. Like, maybe you could get away with the minor version bumps preventing a new endpoint from being seen, but unlike distributed code, it's you, the API provider's risk if you keep the old version alive, not the person using the software.
@nugend, that's correct, however I think the vision here is more to allow a 1:1 mapping between your library code version and API version if you choose. Without any guarantee that 1.2.x version is supported. For instance you could choose to only have special behavior for > 1.4.x and keep the old behavior the same for < 1.4.x, right now that would mean you have to release a new version of the API version (say 2) when which clearly would separate you from your semantic version. I don't think there is any expectation that people would keep a large number of APIs supported at a single time, no more then say 2-3, this just would provide them a mechanism to keep the versions they do support in-sync with their semantic version numbers for APIs that are exposed in both forms.
+1 for this feature.
I'd recommend using this library. You can define Spec
and Version
objects. This would be a great way to separate the what versions a specific API function applies to (Spec
) and the version that the user is requesting through the API call (Version
). Here's an example from their site:
>>> s = Spec('>=0.1.1') # At least 0.1.1
>>> s.match(Version('0.1.1'))
True
>>> s.match(Version('0.1.1-alpha1')) # pre-release satisfy version spec
True
>>> s.match(Version('0.1.0'))
False
>>> s = Spec('==0.1.1')
>>> Version('0.1.1-alpha1') in s
True
>>> Version('0.1.2') in s
False
So, the Hug API might look like this:
@hug.get(versions=Spec('>=0.1.1'))
def endpoint():
pass
And then the version number found in an HTTP URL, CLI argument, or local variable would be an instance of the Version
type. The Hug router would compare the Version
instance to the Spec
instance to see if it's compatible.
I can work on a PR for this feature, but it'll be in a few weeks from now.
Right now hug only supports versioning on a straight numeric value, this works fairly well in most cases where no breaking changes happen between major releases, however it can occasionally fall apart - which unfortunately could lead to the hug API version not staying at all in sync with the codes semantic version. It would be beneficial to support semantic versioning routes natively in hug. One potential way to do this would be to allow a length 3 tuple to be passed into the tuple in addition to a straight int. A convenience named tuple object could be added to make usage explicit:
thanks @vortec for the idea!