Я полностью понимаю, что введение ненулевого нового свойства было бы серьезным изменением в API, которое потребовало бы некоторого контроля версий.Но думаете ли вы, что этот случай также следует рассматривать как критическое изменение?
Только если ваш API основан на RPC.REST, который является просто обобщением Интернета, разработан таким образом, чтобы легко адаптироваться к изменениям.Контент в Интернете постоянно меняется, не нарушая клиентов.Как Web достигает этого?
Хотя я обычно согласен с Voice, на самом деле у меня немного другое мнение.В архитектуре REST сервер или API должны учить клиента тому, как что-либо делать.Как клиент должен знать, что сервер ожидает получить на определенной конечной точке?Swagger или аналогичные подходы к документации в основном полезны для API на основе RPC , но REST имеет HATEOAS.Здесь гипертекст используется для управления состоянием приложения.Это означает, что клиент будет использовать полученный ответ для изучения новых возможностей.
Традиционный поток взаимодействия, используемый в Интернете, заключается в том, что клиент будет вызывать интересующий его URI и получать ответ, который представляется дляПользователь предпринимает дальнейшие действия при.В случае ожидаемого пользовательского ввода сервер вернет веб-форму, где пользователь может ввести данные, которые ожидает сервер.Именно так сервер обучает клиентов тому, что они должны отправлять на сервер.Сервер, конечно, будет проверять ввод при приеме, чтобы избежать ввода строковых литералов в ожидаемые числовые поля и, таким образом, или проверить, существует ли уже такой элемент данных.Таким образом, клиенту не нужно заранее знать, какие данные может ожидать сервер.Если вы введете новое поле, клиент узнает это новое поле после получения ответа.
Аналогичный подход можно и, вероятно, следует использовать в архитектуре REST.Либо повторно используйте HTML-формы, используйте некоторые похожие подходы, такие как halo + json , или определите свой собственный тип носителя, который вы должны зарегистрировать в IANA .Возможно, было бы целесообразно сначала проверить уже существующие типы носителей и посмотреть, предлагают ли они необходимую вам возможность.Клиент, конечно, должен иметь возможность динамически визуализировать форму на основе полученного контента.Это может быть нетривиальной задачей, хотя в качестве ссылки можно использовать множество браузеров.
Хотя HTML-формы не поддерживают PUT
, DELETE
или PATCH
,концепции все еще могут быть применены к REST.Т.е. после нажатия кнопки отправки клиент обычно отправляет все входные данные в представлении application/x-www-form-urlencoded
на сервер, если только клиент не указывает другое enctype
, и сервер должен преобразоватьданные для чего-то, с чем они будут работать дальше, например, для создания нового ресурса, запуска процесса поддержки или вызова другой службы. PUT определяется таким образом, чтобы он мог:
- реконфигурировать целевой ресурс для отражения нового типа мультимедиа
- преобразовать представление PUTв формат, соответствующий формату ресурса, перед сохранением его в качестве нового состояния ресурса
- отклонить запрос с ответом 415 (неподдерживаемый тип носителя), указывающим, что целевой ресурс ограничен его текущим типом носителя.
То, как данные ресурса хранятся на стороне сервера, обычно является деталью реализации, не относящейся к клиенту.Он может быть сохранен просто как объект карты или словаря, содержащий произвольные ключи и значения, которые описывают содержимое, или он может быть отображен на определенные классы, используемые в объектно-ориентированном программировании.Кроме того, он может быть просто сохранен в виде простого текста в файле или в виде байтового двоичного объекта в базе данных.Тем не менее, в идеале сервер может отображать состояние ресурса в различные форматы представления медиа-типов, что также делает согласование типов контента более доминирующим и позволяет избежать типизированных ресурсов .
Вся эта концепция сервера, обучающего клиента тому, что ему нужно, и способности клиента динамически воспроизводить контент на основе полученных данных, позволяет клиентам изучать новые вещи на лету и легко адаптироваться к изменениям.Это на самом деле основная особенность архитектуры REST и один из главных аргументов в пользу того, почему API, у которых множество клиентов не находятся под их контролем, должны стремиться к такой архитектуре.
Должен ли я иметь версию v1что только обновляет a и b, а a v2 обновляет a, b и c?
Вы можете прочитать о Филдинге о версии , которая просто сводится к: не (в смысле вставки видимых клиентом номеров версий внутриURIs).По сути, если вы следуете описанному выше подходу server teaches, client learns
, то в любом случае нет нужды в нумерации версий, за исключением того, что владелец API сам изменяет управление версиями.Клиенты в архитектуре REST все равно получат только последнюю версию или, если быть более точным, версию, которую сервер предоставляет им, и смогут справиться с ней.Только клиенты на основе RPC, которые ожидают, что определенная версия на сервере будет иметь проблемы с адаптацией к этим изменениям, если сервер также не разделяет полученные данные.В таком случае, вероятно, в общем случае предпочтительнее переключение общего пространства имен, чтобы избежать путаницы.
Есть ли лучший способ избежать увеличения номера версии для таких изменений?
Как указано в посте, сервер должен обучать клиентов, а последний должен изучать их возможности по анализу ответов.Это то, что касается обеих сторон.Даже если у вас есть сервер, соблюдающий все ограничения, налагаемые архитектурой REST, клиент, который анализирует и анализирует URI, а не использует имена связей, который ожидает, что ресурсы будут возвращать определенные типы вместо согласования формата представления, который понимают обе стороны, или чтоне желает учиться на сервере и вместо этого применяет запрограммированные в клиенте внеполосные знания, со временем сломается и, следовательно, не сможет взаимодействовать с таким сервером в дальнейшем.
Использует PATCHпрактическое решение?
PATCH - это обычно неверно понимаемый метод HTTP.Это похоже на патчи, используемые в программировании, где патч содержит изменения для применения к некоторому заданному коду для преобразования его в желаемый результат.То же самое на самом деле должно быть сделано через HTTP.Клиент должен взять текущее представление ресурса и вычислить изменения, необходимые для преобразования состояния ресурса в желаемое.Одним из аспектов исправлений, которым обычно пренебрегают, является то, что исправления необходимо применять атомарно.Либо все изменения применяются, либо их не должно быть.
Тип носителя, который склоняется к традиционному исправлению, application/json-patch+json
определен в RFC 6902 , который определяет набор инструкций для применения кресурс рассматривается как объект JSON.С помощью JSON Pointers соответствующие сегменты, которые должны быть изменены в текущем представлении, рассматриваются в документе JSON Patch.
Другой подход к исправлению определен в RFC 7396 , который определяет более практичный подход к применению изменений к исходному ресурсу.Это покрыто application/merge-patch+json
.Разница между JSON Patch и JSON Merge Patch заключается в том, что последний не определяет операции, применяемые к документу, а содержит весь обновленный документ в запросе.Поэтому он опирается на ряд установленных правил.Т.е. если в запросе появляется новое поле, то выполняется вставка этого поля, а если значение существующего поля изменяется, это приводит к обновлению этого поля.Удаление достигается путем обнуления значений.
Более подробное объяснение того, как патчить, можно найти в отличном посте блога Уильяма Дюрана Пожалуйста, не патчите, как идиот .
На практике PATCH
следует использовать, если у вас есть частичные обновления для выполнения состояния ресурса, так как PUT
определено для замены всего содержимого на предоставленное после выполнения некоторых проверок достоверности.Хотя PUT также содержит подсказку о том, как частичное обновление может быть достигнуто за счет перекрывающихся ресурсов, я полагаю, что этот метод довольно необычен.Для данного сценария добавления новых полей при обновлении версии, я думаю, что исправление не является правильным способом, к которому вы должны стремиться, и вместо этого попытайтесь использовать server teaches, client learns
подход, как показано в этом ответе.