Как сделать версию REST URI

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

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

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

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

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

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

11 ответов

Решение

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

Не делайте версии 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, если вы не анализируете их с помощью загрузки кода, и на этом этапе версионирование является спорным.

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

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

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

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

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

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

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

Вы не должны помещать версию в 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

Существует 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-шлюзов.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам