Для меня REST - это идеология, к которой вы хотите стремиться, если у вас есть система, которая должна прослужить долгие годы, которая имеет свободу свободно развиваться, не разбивая вещи на части, которыми вы не можете управлять. Это очень похоже на Интернет, где сервер не может напрямую управлять браузерами, хотя браузеры могут взаимодействовать с любыми изменениями, внесенными в представления веб-сайтов, возвращаемые сервером.
Я читал, что ссылки на HATEOAS отделяют REST API от обычного http API. В таком случае нужно ли REST отдельное имя?
REST делает в основном то, что подразумевает его имя, он передает состояние представления ресурса. Если это так, нам следует придумать новое имя для таких «REST» API, которые действительно являются RPC сзади, чтобы избежать путаницы.
Если вы прочитаете Модель зрелости Ричардсона (RMM) , у вас может сложиться впечатление, что ссылки или элементы управления гипермедиа, как их назвал Фаулер, которые являются обязательными на уровне 3, являются функцией, отделяющей REST от нормальное HTTP-взаимодействие. Однако уровня 3 просто недостаточно для достижения конечной цели развязки.
Большинство так называемых «API REST» действительно прикладывают много усилий для разработки красивых URI, чтобы выразить смысл целевого ресурса клиентскому разработчику. Они придумывают причудливую документацию, сгенерированную их инструментальной поддержкой, например Swagger или аналогичные вещи, которым разработчик клиента должен строго следовать, иначе они не смогут взаимодействовать со своим API. Такие API являются RPC, хотя. Вы не сможете указать тому же клиенту, который взаимодействует с API A, чтобы указывать на API B сейчас, и все еще работать «из коробки», поскольку они могут использовать совершенно разные конечные точки и возвращать разные типы данных для почти одинаковой именованной конечной точки ресурса. Клиент, который пытается использовать немного больше динамического поведения, может узнать тип при разборе конечной точки и ожидать, что URI, такой как .../api/users
, будет возвращать пользователей, когда вдруг API изменил свою структуру URI на что-то вроде .../api/entities
. Что теперь будет? Большинство этих клиентов сломаются, что является явным намеком на то, что целая модель взаимодействия не соответствует одному контуру архитектуры REST.
REST делает упор на имена отношений ссылок, которые должны предоставить клиентам стабильный способ изучения намерений URI, позволяя URI действительно изменяться со временем. URI в основном присоединяется к имени отношения ссылки и в основном представляет собой доступ, что-то, что ясно, что он делает. То есть доступность кнопки может заключаться в том, что вы можете нажать ее, и в результате что-то произойдет. Или доступ к выключателю света может заключаться в том, что свет включается или выключается в зависимости от состояния переключателя освещения.
Имена отношений ссылок теперь предоставляют такую возможность и представляют собой текстовый способ представления чего-то вроде мусорного ведра или символа карандаша рядом с записью таблицы на веб-странице, где вы можете выяснить, что при нажатии на одну удаляется запись из таблица, в то время как другой символ позволяет редактировать эту запись. Такие имена отношений ссылок должны быть либо стандартизированными , либо использовать общепринятые онтологии , либо использовать пользовательских расширений отношений ссылок, как указано в RFC 8288 (Web Linking)
Важно отметить, однако, что URI - это просто URI, который не должен передавать клиенту семантическое значение. Это не означает, что URI не может иметь семантического значения для сервера или API, но клиент не должен пытаться вывести его из самого URI. Это то, для чего предназначено имя отношения ссылки, которое обеспечивает редко меняющуюся часть этого отношения. На конечную точку могут ссылаться несколько разных URI, некоторые из которых могут использовать разные параметры запроса, используемые для фильтрации. Согласно Филдингу каждый из этих URI представляет разные ресурсы:
Определение ресурса в REST основано на простой предпосылке: идентификаторы должны изменяться как можно реже . Поскольку в Интернете используются встроенные идентификаторы, а не серверы ссылок, авторам необходим идентификатор, который точно соответствует семантике, которую они намереваются в гипермедиа-ссылке, что позволяет этой ссылке оставаться статической, даже если результат доступа к этой ссылке может со временем меняться. REST выполняет это путем , определяя ресурс как семантику того, что автор намерен идентифицировать, а не значение, соответствующее этой семантике в момент создания ссылки . Затем он оставляется на усмотрение автора, чтобы убедиться, что идентификатор, выбранный для ссылки, действительно идентифицирует предполагаемую семантику. (Источник 6.2.1 )
Поскольку URI используются для кэширования результатов, они в основном представляют ключи, используемые для кэширования полезной нагрузки ответа. Таким образом, становится очевидным, что при добавлении дополнительных параметров запроса к URI, используемым в запросах GET
, вы в конечном итоге обходите кэши, поскольку ключ еще не сохранен в кэше, и, следовательно, получаете результат другого ресурса, даже если он может быть идентичным (также в представлении ответа) как URI без этого дополнительного параметра.
Интересно, о чем весь этот ажиотаж вокруг REST API. Кажется, это просто метод http с одним дополнительным правилом в ответе.
Короче говоря, это то, что передают эти псевдо-"REST APIs", называемые собой или маркетингом, и многие люди, кажется, понимают.
Шумиха по поводу «REST» возникла из-за неудобств, налагаемых на разработчиков при взаимодействии с другими решениями взаимодействия, такими как Corba, RMI или SOAP, где часто приходится использовать частично коммерческие сторонние библиотеки и инфраструктуры для взаимодействия с такие системы. Большинство языков поддерживают HTTP как клиент, так и сервер из коробки, что устраняет необходимость во внешних библиотеках или инфраструктурах как таковых. В дополнение к этому, решение на основе RPC обычно требует, чтобы сначала были созданы определенные классы-заглушки или скелеты, что обычно выполнялось конвейером сборки автоматически. После обновлений IDL, таких как связывание WSDL или включение схем XSD, необходимо было переделать всю генерацию заглушки, а весь код - просмотреть, чтобы определить, было ли добавлено критическое изменение или нет. Обычно не было доступного явного журнала изменений, что делало изменение или обновление такого материала болью в ...
В этих псевдо-REST-API простой JSON теперь в значительной степени является стандартом де-факто, избегая этапов создания классов-заглушек и анализа собственного кода, чтобы увидеть, не оказали ли некоторые из принудительных изменений негативное влияние на система. Большинство этих API-интерфейсов используют своего рода управление версиями на основе URI, позволяющее разработчику на основе URI видеть, было ли что-то нарушено или нет, имитируя какое-то семантическое управление версиями .
Однако проблема с этим решением заключается в том, что не сам формат представления ответа является версионным, а весь сам API, что приводит к общим проблемам, когда нужно вносить только изменения в части API, поскольку теперь требуется полная версия API. столкнуться В дополнение к этому URI, такие как .../api/v1/users/1234
и .../api/v2/users/1234
, могут представлять одного и того же пользователя и, таким образом, один и тот же ресурс, хотя на самом деле различаются по своей природе, поскольку URI отличается.
В) Какие еще различия существуют?
Несмотря на то, что REST - это просто модель архитектуры, которая не может принудить вас к строгой реализации, вы просто не сможете воспользоваться ее свойствами, если проигнорируете некоторые из ее ограничений . Как упоминалось выше, поддержки HATEOAS еще недостаточно, чтобы действительно отделить всех клиентов от API и, таким образом, получить выгоду от архитектуры REST.
К сожалению, RMM вообще не говорит о типах медиа. Тип мультимедиа в основном определяет способ обработки полученной полезной нагрузки и определяет семантику и ограничения каждого из элементов, используемых в этой полезной нагрузке. То есть если вы посмотрите на text/html
, зарегистрированный в реестре типов носителей IANA , вы увидите, что он указывает на опубликованную спецификацию , которая всегда ссылается на самую последнюю версию HTML. HTML разработан таким образом, чтобы обеспечить обратную совместимость, поэтому не требуется никаких специальных функций управления версиями.
HTML предоставляет, IMO, две важные вещи:
Первый позволяет структурировать данные, давая определенным сегментам или элементам возможность выражать различную семантику, определенную в типе носителя. То есть браузер будет обрабатывать изображение иначе, чем элемент div или элемент article. Сканер может предпочесть ссылки и контент, содержащийся в элементе article, и полностью игнорировать элементы script и image. На основании наличия или отсутствия определенных элементов могут возникать даже некоторые технологические различия.
Включение поддержки форм - это очень важная вещь в REST, поскольку эта функция позволяет серверу обучать клиента тому, что ему нужно в качестве входных данных. Большинство так называемых «REST API» просто заставляют разработчика просматривать свою документацию, которая может быть устаревшей, неправильной или неполной, и отправлять данные в предопределенную конечную точку в соответствии с документацией. В случае устаревшей или неполной документации, как клиент сможет отправлять данные на сервер? Более того, сервер никогда не сможет измениться, так как в основном документация - это правда, а API должен соответствовать документации.
К сожалению, поддержка форм все еще находится в зачаточном состоянии. Помимо HTML, который предоставляет <form>...</form>
, у вас есть несколько попыток форм на основе JSON, таких как hal-form , halo-json (halform) , Ion или гидра . Ни у одного из них пока нет широкой поддержки библиотек или фреймворков, так как некоторые из этих представлений форм еще не доработали свою спецификацию о том, как поддерживать формы более эффективно.
К сожалению, другие типы мультимедиа могут не использовать полуструктурированный контент или предоставлять поддержку форм, которые обучают клиента потребностям сервера, хотя в целом они все еще ценны для REST. Во-первых, с помощью веб-ссылки поддержка ссылок может быть добавлена к типам мультимедиа, которые не поддерживают их. Во-вторых, сами данные вовсе не обязательно должны быть основаны на тексте, чтобы приложение могло их использовать дальше. То есть изображения, как правило, видео кодируются и в любом случае основаны на байтах, но клиент может представить их пользователям.
Основной момент, касающийся медиа-типов, заключается в том, что, как уже сказал Филдинг в одном из цитируемых им постов в блоге, представления не следует путать с типами. Филдинг заявил, что:
REST API никогда не должен иметь «типизированных» ресурсов, значимых для клиента. Авторы спецификаций могут использовать типы ресурсов для описания реализации сервера за интерфейсом, но эти типы должны быть неактуальными и невидимыми для клиента. Единственными типами, которые важны для клиента, являются тип медиа текущего представления и стандартизированные имена отношений.
В отличном сообщении в блоге Йорн Вильдт объяснил, что такое "typed" resource
и почему архитектура REST не должна использовать такие типы. По сути, чтобы подвести итог публикации в блоге, клиент, ожидающий, что конечная точка ../api/users
вернет предварительно предполагаемую полезную нагрузку данных, может прерваться, если сервер добавит дополнительные неожиданные поля, переименует существующие поля или пропустит ожидаемые поля. Этого связывания можно избежать с помощью простого согласования типа контента , когда клиент сообщает серверу, какие возможности он поддерживает, и клиент выбирает представление, которое наилучшим образом соответствует целевому ресурсу. Если сервер не может поддержать клиента с представлением, клиент поддерживает сервер, должен ответить с ошибкой (или представление по умолчанию), клиент мог войти, чтобы сообщить пользователю.
По сути, это именно то, что означает имя REST, передача представления состояния ресурса, в котором представление может отличаться в зависимости от формата представления, определенного выбранным типом носителя. Хотя HATEOAS может быть одним из наиболее очевидных изменений между REST и HTTP-решением, не основанным на REST, это, безусловно, не единственный фактор, который составляет полезную нагрузку в REST. Я надеюсь, что смогу пролить некоторый свет на намерение разъединения и то, что сервер должен учить клиентов тому, что сервер ожидает от форм и что доступность URI фиксируется именами связей. Все эти крошечные аспекты в совокупности составляют REST, и вы получите выгоду от REST, к сожалению, только в том случае, если вы уважаете все его ограничения, а не только те, которые либо легко получить, либо какие у вас есть настроение для реализации.