Подтвердить что ты не робот

Поддержка нескольких версий API в колбе

Я начал создавать веб-сервис RESTful с Flask и Python, и мне интересно, как поддерживать несколько версий API в одном проекте. Я собираюсь поместить запрошенную версию API в URL-адрес следующим образом:

/myapp/v1/Users

Через некоторое время я хочу добавить еще одну конечную точку в версии 1.1 API и сохранить все, начиная с версии v1, которая не изменилась:

/myapp/v1.1/Users   <= Same as in v1
/myapp/v1.1/Books

В версии v2 изменена точка-пользователи:

/myapp/v2/Users   <= Changed in v2
/myapp/v2/Books   <= Same as in v1.1

и т.д.

Рассматривая этот вопрос, самый простой способ, вероятно, будет примерно таким:

@app.route('/<version>/users')
def users(version):
    # do something
    return jsonify(response)

Но я могу представить, что с каждой новой версией API это будет сложнее поддерживать. Поэтому мне было интересно, есть ли лучше (= проще поддерживать и лучше структурировать) способ достичь этого с помощью Flask?

4b9b3361

Ответ 1

Я являюсь автором принятого ответа на вопрос, на который вы ссылались. Я думаю, что подход /<version>/users не очень эффективен, как вы говорите. Если вам нужно управлять тремя или четырьмя различными версиями, вы получите код спагетти.

Идея nginx, которую я предложил, лучше, но имеет недостаток, что вам нужно разместить два отдельных приложения. В то время я пропустил упоминание третьей альтернативы, которая должна использовать план для каждой версии API. Например, рассмотрим следующую структуру приложения (значительно упрощенную для ясности):

my_project
+-- api/
    +-- v1/
        +-- __init__.py
        +-- routes.py
    +-- v1_1/
        +-- __init__.py
        +-- routes.py
    +-- v2/
        +-- __init__.py
        +-- routes.py
    +-- __init__.py
    +-- common.py

Здесь у вас есть api/common.py, который реализует общие функции, необходимые всем версиям API. Например, вы можете иметь вспомогательную функцию (не оформленную как маршрут), которая отвечает на ваш маршрут /users, который идентичен в v1 и v1.1.

routes.py для каждой версии API определяет маршруты и, при необходимости, вызывает функции common.py, чтобы избежать дублирования логики. Например, ваши v1 и v1.1 routes.py могут иметь:

from api import common

@api.route('/users')
def get_users():
    return common.get_users()

Обратите внимание на api.route. Здесь api является планом. Наличие каждой версии API, реализованной в качестве плана, помогает объединить все с правильными версиями URL. Вот пример кода установки приложения, который импортирует чертежи API в экземпляр приложения:

from api.v1 import api as api_v1
from api.v1_1 import api as api_v1_1
from api.v2 import api as api_v2

app.register_blueprint(api_v1, url_prefix='/v1')
app.register_blueprint(api_v1_1, url_prefix='/v1.1')
app.register_blueprint(api_v2, url_prefix='/v2')

Эта структура очень хороша, потому что она поддерживает все версии API, но они обслуживаются одним и тем же приложением. В качестве дополнительного преимущества, когда придет время прекратить поддержку v1, вы просто удаляете вызов register_blueprint для этой версии, удаляете пакет v1 из ваших источников, и все готово.

Теперь, со всем этим сказанным, вы должны действительно приложить усилия для разработки своего API таким образом, чтобы свести к минимуму риск пересмотра версии. Учтите, что для добавления новых маршрутов не требуется новая версия API, вполне нормально расширять API новыми маршрутами. И изменения в существующих маршрутах иногда могут быть спроектированы таким образом, чтобы не влиять на старых клиентов. Иногда бывает менее болезненно пересматривать API и иметь больше свободы для изменения вещей, но в идеале это происходит не так часто.