it-swarm.com.ru

Как версия REST URIs

Каков наилучший способ для версии REST URI? В настоящее время у нас есть версия # в самом URI, т.е.

http://example.com/users/v4/1234/

для версии 4 этого представления.

Версия принадлежит в queryString? то есть.

http://example.com/users/1234?version=4

Или версионирование лучше всего выполнить другим способом?

103
Mike Pone

Я бы сказал, что лучше сделать его частью самого URI (вариант 1), потому что v4 идентифицирует ресурс, отличный от v3. Параметры запроса, как во втором варианте, лучше всего использовать для передачи дополнительной информации (запроса), связанной с request , а не resource .

30
Zef Hemel

Не делайте версии URL, потому что ... 

  • вы нарушаете постоянные ссылки
  • Изменения URL будут распространяться как болезнь через ваш интерфейс. Что вы делаете с представлениями, которые не изменились, но указывают на представление, которое изменилось? Если вы измените URL, вы сломаете старых клиентов. Если вы оставите URL, ваши новые клиенты могут не работать.
  • Версионные типы носителей - гораздо более гибкое решение.

Предполагая, что ваш ресурс возвращает какой-то вариант application/vnd.yourcompany.user + xml, все, что вам нужно сделать, - это создать поддержку для нового типа носителя application/vnd.yourcompany.userV2 + xml и с помощью магии согласования контента, v1 Клиенты v2 могут мирно сосуществовать.

В интерфейсе RESTful наиболее близким к контракту является определение типов мультимедиа, которыми обмениваются клиент и сервер.

URL-адреса, которые клиент использует для взаимодействия с сервером, должны быть предоставлены сервером, встроенным в ранее полученные представления. Единственный URL-адрес, который должен знать клиент, - это корневой URL-адрес интерфейса. Добавление номеров версий в URL имеет смысл только в том случае, если вы создаете URL-адреса на клиенте, чего не следует делать с интерфейсом RESTful.

Если вам нужно изменить типы мультимедиа, которые сломают существующих клиентов, создайте новый и оставьте свои URL в покое!

И для тех читателей, которые сейчас говорят, что это бессмысленно, если я использую application/xml и application/json в качестве медиа-типов. Как мы должны их версии? Вы не. Эти типы мультимедиа в значительной степени бесполезны для интерфейса RESTful, если вы не анализируете их с помощью загрузки кода, и на этом этапе версионирование является спорным вопросом.

191
Darrel Miller

Ах, я снова надеваю свою старую сварливую шляпу.

С точки зрения ReST это не имеет значения вообще. Не колбаса.

Клиент получает URI, которому он хочет следовать, и обрабатывает его как непрозрачную строку. Поместите все, что вы хотите, клиент знает no о такой вещи, как идентификатор версии.

Клиент знает, что он может обрабатывать тип носителя, и я посоветую последовать совету Даррела. Кроме того, я лично считаю, что необходимость изменения формата, используемого в спокойной архитектуре 4 раза, должна принести огромные массивные предупреждения о том, что вы делаете что-то серьезно неправильно, и полностью обойти необходимость разработки типа носителя для устойчивости к изменениям.

Но в любом случае клиент может обрабатывать документ только в том формате, который он может понять, и переходить по ссылкам в нем. Нужно знать о связи связей (переходов). Так что то, что в URI, совершенно не имеет значения.

Я лично проголосовал бы за http: // localhost/3f3405d5-5984-4683-bf26-aca186d21c04

Совершенно действительный идентификатор, который не позволит дальнейшим разработчикам клиентов или лицам, касающимся системы, задаться вопросом, следует ли ставить v4 в начале или в конце URI (и я полагаю, что с точки зрения сервера у вас не должно быть 4 версии, но 4 типа носителей).

21
SerialSeb

Вы не должны помещать версию в URL, вы должны поместить версию в заголовок Accept запроса - см. Мой пост в этой теме:

Лучшие практики для управления версиями API?

Если вы начнете вставлять версии в URL, вы получите глупые URL, такие как: http://company.com/api/v3.0/customer/123/v2.0/orders/4321/

И есть еще куча других проблем - смотрите мой блог: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html

11
jeremyh

Эти (менее конкретные) SO вопросы о REST версиях API могут быть полезны:

5
Pete TerMaat

Я хотел создать версионные API и нашел эту статью очень полезной:

http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http

Есть небольшой раздел «Я хочу, чтобы мой API был версионным». Я нашел это простым и легким для понимания. Суть в том, чтобы использовать поле Accept в заголовке для передачи информации о версии.

2
Asma Zubair

Если службы REST требуют аутентификации перед использованием, вы можете легко связать ключ/токен API с версией API и выполнить маршрутизацию внутри. Чтобы использовать новую версию API, может потребоваться новый ключ API, связанный с этой версией.

К сожалению, это решение работает только для API на основе аутентификации. Тем не менее, он хранит версии вне URI.

2
UberSteve

Если вы используете URI для управления версиями, тогда номер версии должен быть в URI корня API, поэтому его может включать каждый идентификатор ресурса.

Технически API REST не прерывается при изменении URL (результат ограничения унифицированного интерфейса). Он прерывается только в том случае, если связанная семантика (например, специфическая для API вокаба RDF) изменяется не обратно совместимым способом (редко). В настоящее время многие пользователи не используют ссылки для навигации (ограничение HATEOAS) и вокабу для аннотирования своих ответов REST (самоописательное ограничение сообщений), поэтому их клиенты ломаются.

Пользовательские типы MIME и управление версиями MIME-типов не помогают, поскольку помещение связанных метаданных и структуры представления в короткую строку не работает. Ofc. метаданные и структура будут часто меняться, и поэтому номер версии тоже ... 

Поэтому, чтобы ответить на ваш вопрос, лучше всего аннотировать ваши запросы и ответы с помощью вокабсов ( Hydra , связанные данные ) и забыть о версиях или использовать их только при несовместимых обратно изменениях вокаба (например, если вы хотите заменить вокаб на другой).

1
inf3rno

Я бы включил версию в качестве необязательного значения в конце URI. Это может быть суффикс типа/V4 или параметр запроса, который вы описали. Вы можете даже перенаправить/V4 на параметр запроса, чтобы поддерживать оба варианта. 

1
Paul Morgan

Я голосую за то, чтобы сделать это в MIME-типе, но не в URL-адресе .... Но причина не та, что у других парней.

Я думаю, что URL-адрес должен быть уникальным (за исключением тех переадресаций) для поиска уникального ресурса . Итак, если вы принимаете /v2.0 в URL-адресах, почему это не /ver2.0, или /v2/, или /v2.0.0? Или даже -alpha и -beta? (тогда это полностью становится понятием semver )

Таким образом, версия в MIME-типе является более приемлемым, чем URL.

0
Yarco

Существует 4 разных подхода к управлению версиями API:

  • Добавление версии в путь URI:

    http://example.com/api/v1/foo
    
    http://example.com/api/v2/foo
    

    Если у вас есть критические изменения, вы должны увеличить версию, например: v1, v2, v3 ... 

    Вы можете реализовать контроллер в своем коде так:

    @RestController
    public class FooVersioningController {
    
    @GetMapping("v1/foo")
    public FooV1 fooV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping("v2/foo")
    public FooV2 fooV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Запрос параметров версии:

    http://example.com/api/v2/foo/param?version=1
    http://example.com/api/v2/foo/param?version=2
    

    Параметр version может быть необязательным или обязательным в зависимости от того, как вы хотите использовать API.

    Реализация может быть похожа на это:

    @GetMapping(value = "/foo/param", params = "version=1")
    public FooV1 paramV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/param", params = "version=2")
    public FooV2 paramV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Передача пользовательского заголовка:

    http://localhost:8080/foo/produces
    

    С заголовком:

    headers[Accept=application/vnd.company.app-v1+json]
    

    или же:

    headers[Accept=application/vnd.company.app-v2+json]
    

    Наибольшим преимуществом этой схемы является в основном семантика: вы не загромождаете URI чем-либо связанным с управлением версиями.

    Возможная реализация:

    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
    public FooV1 producesV1() {
        return new FooV1("firstname lastname");
    }
    
    @GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
    public FooV2 producesV2() {
        return new FooV2(new Name("firstname", "lastname"));
    }
    
  • Изменение имени хоста или использование шлюзов API:  

    По сути, вы перемещаете API с одного имени хоста на другое. Вы можете даже назвать это здание новым API для тех же ресурсов. 

    Также вы можете сделать это с помощью API-шлюзов.

0
Javier C.