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 using accept header #4239

Merged
merged 23 commits into from Feb 3, 2022
Merged

API versioning using accept header #4239

merged 23 commits into from Feb 3, 2022

Conversation

Marishka17
Copy link
Contributor

@Marishka17 Marishka17 commented Jan 25, 2022

Motivation and context

This PR contains a new API versioning scheme using AcceptHeaderVersioning
I've tried to implement an approach like API versioning for HTTP REST interfaces (best practices) (application/vnd.cvat.v1.0+json) but in this case, I couldn't fix unavailable drf-spectacular documentation. I guess It may be not supported in the current implementation

How has this been tested?

Checklist

License

  • I submit my code changes under the same MIT License that covers the project.
    Feel free to contact the maintainers if that's a concern.
  • I have updated the license header for each file (see an example below)
# Copyright (C) 2022 Intel Corporation
#
# SPDX-License-Identifier: MIT

@Marishka17 Marishka17 changed the title [WIP] API versioning API versioning using accept header Jan 28, 2022
@Marishka17 Marishka17 force-pushed the mk/versioning branch 5 times, most recently from b33bf82 to 06a0ee3 Compare January 31, 2022 14:07
run: |
docker-compose -f docker-compose.yml -f docker-compose.dev.yml -f ./tests/docker-compose.email.yml -f tests/docker-compose.file_share.yml -f components/serverless/docker-compose.serverless.yml up -d --build
/bin/bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' ${API_ABOUT_PAGE})" != "401" ]]; do sleep 5; done'
/bin/bash -c 'while [[ $(curl -s -o /dev/null -H "Accept: application/vnd.cvat+json; version=1.0" -w "%{http_code}" ${API_ABOUT_PAGE}) != "401" ]]; do sleep 5; done'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , what do you think if by default we will use the latest version of API? Thus if we don't specify accept header, DRF will use the latest one. I know that the link https://github.com/interagent/http-api-design/blob/master/en/foundations/require-versioning-in-the-accepts-header.md says that it is a bad practice. But GitHub uses the strategy: https://docs.github.com/en/rest/overview/media-types

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nmanovic , Also rest_framework documentation doesn't say that this is a bad practice, let's use the default version. In this case, I guess we can miss accept header in client/tests. I'll update it.

CHANGELOG.md Show resolved Hide resolved
@@ -36,24 +37,30 @@ def generate_image_file(filename, size=(100, 100)):
return f

class ForceLogin:
def __init__(self, user, client):
def __init__(self, user, client, version=settings.BACKEND_VERSIONS.V1_0):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , One more problem if we don't have a default version. I don't think that it is good idea to have BACKEND_VERSIONS.V1_0 and ACCEPT_HEADER_TEMPLATE in settings.

Accept: application/vnd.cvat+json; version=1.0
"""

def determine_version(self, request, *args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , Do we need the method if we have a default version?

# Need to add 'api-docs' here as a workaround for include_docs_urls.
'ALLOWED_VERSIONS': ('v1', 'api-docs'),
'ALLOWED_VERSIONS': (*BACKEND_VERSIONS.list(), 'api-docs', 'downloading'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to remove api-docs and downloading from the list.

@@ -36,7 +36,7 @@ Common scheme for our REST API is `<VERB> [namespace] <objects> <id> <action>`.
- Allow filtering, sorting, and pagination
- Maintain good security practices
- Cache data to improve performance
- Versioning our APIs (e.g. `/api/v1`, `/api/v2`). It should be done when you
- Versioning our APIs (e.g. `/api`, `/api/v2`). It should be done when you
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , need to update the statement. It looks wrong now (e.g., /api/v2)

headers: {
Authorization: `Token ${authKey}`,
Accept: acceptHeader,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , @bsekachev , should UI work with the latest version (=default) of REST API always? Thus we can skip acceptHeader for tests and UI.

@@ -12,12 +12,14 @@

def test_non_admin_cannot_see_others():
for username in ['dummy1', 'worker1', 'user1', 'business1']:
response = requests.get(config.get_api_url('users'), auth=(username, config.USER_PASS))
response = requests.get(config.get_api_url('users'), auth=(username, config.USER_PASS),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , tests should test all versions. Thus if we have a default version, right now it will be enough. Let's discuss. Really want to find the right approach.

utils/cli/cli.py Outdated
@@ -34,6 +34,8 @@ def main():
with requests.Session() as session:
api = CVAT_API_V1('%s:%s' % (args.server_host, args.server_port), args.https)
cli = CLI(session, api, args.auth)
#TODO add version indication
session.headers.update({'Accept': 'application/vnd.cvat+json; version=1.0'})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, probably CLI should work with the latest (default version) of API.

@Marishka17 Marishka17 changed the title API versioning using accept header [WIP]API versioning using accept header Feb 2, 2022
@Marishka17 Marishka17 changed the title [WIP]API versioning using accept header API versioning using accept header Feb 2, 2022
@Marishka17
Copy link
Contributor Author

@nmanovic , I've updated the API version to 2.0 as you said yesterday (I didn't do it before because I believed that we should have done tasks with server code redesigning and separating it to standalone applications).
Also, I've added a test for checking the version for server/about endpoint.
I've found several ways to version codebase (simply extend serializer, an approach like migrations, and others) and I guess we should discuss this moment with the team to choose the best approach for us. So It should be another task.

# Need to add 'api-docs' here as a workaround for include_docs_urls.
'ALLOWED_VERSIONS': ('v1', 'api-docs'),
'rest_framework.versioning.AcceptHeaderVersioning',
'ALLOWED_VERSIONS': ('1.0', '2.0'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Marishka17 , do we support 1.0?

Copy link
Contributor

@nmanovic nmanovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nmanovic nmanovic merged commit 83126c7 into develop Feb 3, 2022
@nmanovic nmanovic deleted the mk/versioning branch February 3, 2022 19:50
@Marishka17
Copy link
Contributor Author

@nmanovic, Should we also register vnd MIME type?

@nmanovic
Copy link
Contributor

@Marishka17 , we should. Need to contact OSPDT.

@nmanovic nmanovic mentioned this pull request Mar 4, 2022
7 tasks
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

Successfully merging this pull request may close these issues.

None yet

2 participants