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

API versioning #127

Closed
inglesp opened this issue May 21, 2013 · 8 comments
Closed

API versioning #127

inglesp opened this issue May 21, 2013 · 8 comments
Milestone

Comments

@inglesp
Copy link
Contributor

inglesp commented May 21, 2013

In docs/api.rst we imply that the API version number will change when admin2 changes. However, I think this is backwards: it should be the responsibility of the user admin2 to update the version number, since they might want to change the API that they expose to their end users.

As such, we'll need to provide a mechanism for a user to associate a ModelAdmin2 with an API version.

This might look like:

class BlogAdmin(ModelAdmin2):
    version = 2
    ...

This version attribute would then be used to construct the URLs.

Thoughts?

@gregmuellegger
Copy link
Contributor

That is an valid and interesting problem since we have more than one author for the API.

  1. The API of the Admin2 that is exposing the API index, we are controlling this API so we can set the versioning
  2. The API for every single ModelAdmin2 which the user can modify by changing the API views on the ModelAdmin2 object. Their version can chang independently.

So we would need a versioning scheme in the URL like:

/api/v1/blog/post/v3/

That kind of looks ugly... any other thoughts on this?

@inglesp
Copy link
Contributor Author

inglesp commented May 22, 2013

Agree this looks ugly! It's also unusual, and I can't recall seeing a single example of this anywhere else. I think I would find this unacceptable, and I suspect many of our users would too.

This would mean that once we hit our 1.0 release, we're going to have to ensure that the API that we're in control of doesn't change in a back-incompatible way. This shouldn't be too hard, since I think this part of the API is read-only. We will just have to ensure that we don't remove any data from it.

@pydanny
Copy link
Member

pydanny commented May 23, 2013

I agree that we have to have the ability to set the API as a project. I disagree that once we hit our 1.0 release we have to make the API doesn't change in a backwards compatible way. Why not?

  1. That locks us in too much. We'll hate this policy later.
  2. If people don't want to upgrade, they don't have to.
  3. If you break the API but have URL versioning schemes, developers will cook up shims. If they could do it for requests, they can do it for django-admin2.

Okay then, as for versioning schemes, assuming:

class BlogAdmin(ModelAdmin2):
    version = 2
  • /api/v1/blog/post/v3/ is ugly
  • /api/v1/v3/blog/post/ is ugly too.
  • /api/v1-3/blog/post/ is confusing
  • /api/v1.3/blog/post/ is meaningless

I'm not sure there is a good way to handle this so I think we'll have to deal with the worst of all evils. 🐸

@gregmuellegger
Copy link
Contributor

Maybe we shouldn't take too much effort to push all the available API resources into one endpoint. It might be easier and more logical for each ModelAdmin2 to have its own endpoint. In kind of URL design this might look like:

# this is what the djadmin2.core.Admin2 exposes to the public
/admin2/api/v1/

# The API of the `ModelAdmin2` for `blog.Post`.
/admin2/blog/post/api/v1/

# The blog post admin will have one resource for every ID, e.g.
/admin2/blog/post/api/v1/42/
/admin3/blog/post/api/v1/128/
...

# The blog post API can increment its API version indepently
/admin2/blog/post/api/v2/

# or it might opt to not support an API at all...
Request:
    GET /admin2/blog/post/api/v1/

Response:
    HTTP 404 Not Found

The generic entrypoint at /admin2/api/v1/ will then list all the registered ModelAdmin2s and their endpoints including the version:

Request:
    GET /admin2/api/v1/

Response:
    HTTP 200 OK

    {
        "version": "1.0",
        "admins": [
            {
                "app_label": "blog",
                "model_name": "post",
                "endpoints": [
                    {
                        "url": "http://localhost:8000/admin2/blog/post/api/v1/",
                        "version": "1.0"
                    },
                    {
                        "url": "http://localhost:8000/admin2/blog/post/api/v1.1/",
                        "version": "1.1"
                    },
                    {
                        "url": "http://localhost:8000/admin2/blog/post/api/v2/",
                        "version": "2.0"
                    }
                ]
            },
            {
                "app_label": "blog",
                "model_name": "comment",
                "endpoints": [
                    {
                        "url": "http://localhost:8000/admin2/blog/comment/api/v1/",
                        "version": "1.0"
                    }
                ]
            },
            # this means that the auth.User admin is registered but doesn't support an API.
            {
                "app_label": "auth",
                "model_name": "user",
                "endpoints": []
            }
        ]
    }

@pydanny
Copy link
Member

pydanny commented May 29, 2013

@gregmuellegger - I like this approach. Let's do it. If we have to change it later for some unanticipated reason, we shall.

gregmuellegger added a commit to gregmuellegger/django-admin2 that referenced this issue Jun 3, 2013
gregmuellegger added a commit to gregmuellegger/django-admin2 that referenced this issue Jun 3, 2013
gregmuellegger added a commit to gregmuellegger/django-admin2 that referenced this issue Jun 4, 2013
@paurosello
Copy link

I prefer this approach but I will leave another option I was reading about just in case.

Http-Headers to select between the different backwards-incompatible endpoints

Pros:
-Prettier URL (only django-admin2's version in the URL)

Cons:
-It's easier and more library-friendly to change URL in request than Request-Headers
-Implementation difficulty?

PD: This is how Stripe API currently manages versioning https://stripe.com/docs/api#versioning

@pydanny
Copy link
Member

pydanny commented Jun 18, 2013

@paurosello That's an interesting idea but I think we'll go with @gregmuellegger's approach. 💇

@pydanny
Copy link
Member

pydanny commented Jul 6, 2013

Hey @gregmuellegger, can we close this ticket?

@auvipy auvipy closed this as completed Nov 8, 2016
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

5 participants