Как оскорбить разработчика via Geek & Poke
Мы в 1cloud занимаемся построением облачного сервиса — наши пользователи могут заказывать у нас виртуальные серверы, и очень часто на них запускаются сайты. Мы уже рассказывали о том, как ускорить загрузку веб-страниц, а сегодня поднимем еще одну интересную тему — каким на самом деле должны быть веб-приложения, чтобы считаться RESTful? Интересный материал на эту тему в блоге образовательного сервиса Recurse Center написала Лорен Лонг (Lauren Long) — мы представляем вашему вниманию адаптированный перевод этой заметки.
Если вы занимаетесь веб-программированием, то наверняка слышали о REST. Многие, такие как я, зачастую делают вид, что знают о нем все, но теряются, когда им задают вопрос, являются ли написанные ими приложения RESTful. «Я использую с html, получается RESTful, правильно?». Настало время раз и навсегда выяснить, что означает этот приятный слуху модный термин.
Что такое REST
REST – аббревиатура для Representational State Transfer (дословно что-то вроде «передача состояния представления»). Это набор принципов разработки, позволяющих сделать передачу данных в сети более гибкой и масштабируемой. Эти принципы отвечают на ряд вопросов: что есть базовые компоненты системы, как они взаимодействуют между собой, как мы можем быть уверенными, что разные части системы могут быть взаимозаменяемыми в любое время, как система может быть масштабирована для работы с миллиардами пользователей?
Рой Филдинг во время выступления на OSCON08
Сам термин «REST» впервые был введен Роем Филдингом (Roy T. Fielding) в его кандидатской диссертации «Архитектурные стили и разработка интернет-ориентированной программной архитектуры» в 2000 году. На момент публикации его работы World Wide Web (то есть веб) уже была весьма популярной. Филдинг рассмотрел вопрос в ретроспективе и проанализировал черты, позволившие www стать более успешной, чем конкурирующие протоколы. Затем он сформулировал основные принципы, позволяющие сделать сетевое взаимодействие Web-like. REST – это общий набор инструментов, не заточенных исключительно под Web, но позволяющий подстраиваться под другие распределенные системы, в том числе, встроенные. Но REST – это и не протокол в прямом смысле. По крайней мере, пока в нем не прописаны четкие параметры выполнения.
Условия Филдинга
В своей диссертационной работе Филдинг приводит несколько параметров или условий для архитектуры системы, чтобы ее можно было считать RESTful. Ниже я приведу краткий обзор каждого из них и попытаюсь объяснить, как Web может им удовлетворять, используя свои ключевые технологии: HTML, HTTP и URI (то же самое, что и URL, для нас сейчас эта разница несущественна).
Система «сервер-клиент»
Ключевое условие по Филдингу: сеть должна быть построена на взаимодействии клиентов и серверов. В данном случае сервер – это компьютер, где хранятся востребованные данные, а клиент – компьютер, который стремится воспользоваться хранимыми на сервере ресурсами. Вы входите в интернет, ваш компьютер посылает HTTP-запрос для того чтобы начать пользоваться информацией с сервера. В системе RESTful должна использоваться модель «сервер-клиент», даже если иногда ее отдельные компоненты выступают в обеих ролях одновременно.
Альтернативой данному виду архитектуры следует назвать архитектуру, основанную на управлении событиями (event-based). В такой модели каждый компонент транслирует события непрерывно, пытаясь получать информацию о подходящих для себя событиях от других компонентов. То есть никакого взаимодействия «один на один», только передача и улавливание запросов. Для системы RESTful такой вариант является неприемлемым.
Принцип stateless
Термины stateful и stateless описывают, нужно ли компьютеру или программе устанавливать и запоминать одно или несколько предшествующих событий в последовательности взаимодействия с пользователем, другим компьютером или программой, устройством или внешним элементом. В данном случае stateless означает, что все методы объекта работают вне какого-либо контекста или локального состояния объекта. Клиентам и серверам нет необходимости хранить данные о каждом состоянии друг друга. Если клиент не взаимодействует с сервером, последнему нет нужды знать о состоянии первого. При этом сервер также не хранит информацию о предыдущих запросах. Каждый запрос рассматривается вне контекста, как отдельный.
Единый интерфейс
Это условие гарантирует, что и клиент и сервер разговаривают на одном языке, что позволят каждой части быть взаимозаменяемой, ее можно усовершенствовать без прерывания работы всей системы. Это достигается через введение 4 дополнительных условий: распознавание ресурсов, управление ресурсами через образы (или репрезентации), self-descriptive сообщения и гипермедиа.
Параметр интерфейса 1: распознавание ресурсов.
В терминологии REST, источниками (ресурсами) могут выступать HTML документы, изображения, информация о конкретном пользователе и так далее. Каждый из них может распознаваться через заданный идентификатор. «Заданный» в том смысле, что он не меняется в процессе взаимодействия. Он не меняется даже при смене состояния ресурса. Если источник переходит на другой идентификатор, сервер пошлет клиенту информацию о неверном запросе вместе со ссылкой на новое местоположение ресурса.
Web для распознавания источника использует URI и HTTP как типовой протокол взаимодействия. Для размещения источника на сервере клиент делает HTTP GET запрос к URI, который его идентифицирует. Как только вы вводите какой-либо адрес в браузере, он отправляет URI запрос GET. Если последний получает сообщение OK с кодом 200 и HTML-документ, страница отрисовывается на экране.
Параметр интерфейса 2: управление ресурсами через представления
Второе дополнительное условие «единого интерфейса» касается вопроса управления ресурсами. Это происходит через отправку клиентом серверу представлений, обычно в виде объекта формата JSON (XML-подобный формат), содержащий информацию о том, что тот хотел бы изменить, исправить или удалить. В системе REST сервер имеет полный контроль над ресурсами и полностью отвечает за любые изменения в них. Если клиент желает что-либо поправить, он отправляет серверу образ того, как все это должно выглядеть. Сервер рассматривает данный запрос в качестве предложения, но по-прежнему сохраняет над страницами исключительный контроль.
Давайте рассмотрим пример с блогами пользователей. Когда пользователь создает новый пост, компьютер дает понять серверу, что его нужно добавить. Для этого он отправляет ему запрос в виде HTTP POST или PUT с его содержанием. Назад компьютер получает ответ с указанием, был ли пост в итоге создан или информацию об ошибке. Если речь идет не об интерфейсе REST, клиент может отправлять конкретные инструкции дальнейших действий. В случае с REST достаточно послать представление того, как должна выглядеть страница поста в окончательном варианте.
Параметр интерфейса 3: self-descriptive сообщения
Self-descriptive сообщения должны содержать всю необходимую получателю информацию для его понимания. Никаких дополнительных сведений другим сообщением или документом. Для того чтобы понять, как это условие применимо в Web, рассмотрим пример HTTP-запроса и ответа на него.
Допустим, пользователь вводит в адресной строке браузера адрес страницы www.example.com. Браузер отправляет следующий HTTP-запрос:
GET / HTTP/1.1
Host: www.example.com
Это сообщение содержит всю необходимую и достаточную информацию: мы используем метод HTTP и протокол HTTP 1.1.
Сервер может прислать следующий ответ на подобный запрос:
HTTP/1.1 200 OK
Content-Type: text/html
<!DOCTYPE html>
<html>
<head>
<title>Home Page</title>
</head>
</body>
<div>Hello World!</div>
<a href= “http://www.recurse.com”> Check out the Recurse Center! </a>
<img src="awesome-pic.jpg">
</body>
</html>
Это сообщение также отвечает признакам self-descriptive. Оно говорит пользователю, как следует понимать сообщение, определяя тип содержания как text/html. У пользователя есть вся информация, чтобы разобраться в сообщении правильно.
Представим иной вариант, при котором сервер в первом сообщении присылал бы бинарный код, а в последующих объяснял бы клиенту, как его следует воспринимать – как образ или как фрагмент кода. Если порядок сообщений по каким-либо причинам перепутан, расшифровать его будет весьма затруднительно.
Параметр интерфейса 4: гипермедиа
Под звучным термином «гипермедиа» обычно понимают сведения, которые высылает сервер клиенту, чтобы сориентировать его в дальнейших действиях. Проще говоря – какие следующие запросы клиент может отправить. В системе REST серверы высылают подобную информацию только в виде гипермедиа.
HTML – один из вариантов гипермедиа. Чтобы в этом разобраться, давайте еще раз взглянем на ответ сервера, приведенный выше.
<a href= “http://www.recurse.com”> Check out the Recurse Center! </a>
означает, что если клиент желает перейти по ссылке, он может отправить запрос GET на адрес www.recurse.com.<img src="awesome-pic.jpg">
сообщает клиенту, что получить картинку страницы можно, отправив GET на адрес www.example.com/awesome-pic.jpg.Итак «единый интерфейс» означает, что соблюдены все приведенные выше условия: идентификаторы имеются для каждой страницы, ресурсами можно управлять через обмен образами между сервером и клиентом, сообщения отвечают принципу self-descriptive и состоят из гипермедиа. Это, пожалуй, самый важный атрибут системы RESTful, позволяющий пользователям правильно и вовремя реагировать на изменения. Сервер может скорректировать основную реализацию, не прерывая взаимодействие со всеми клиентами, потому что каждое такое взаимодействие автономно. Идентификаторы в таком случае не изменяются, а гипермедиа дает клиентам сведения о процессах, которые необходимо произвести в дальнейшем. Сервер не обязан хранить всю информацию о клиенте и прилагать дополнительные усилия, чтобы ему угодить. И наоборот.
Другие условия Филдинга: кэширование, многослойная система, кодировка по запросу
Первое условие касается необходимости того, что ответы сервера должны быть помечены как кэшируемые и не кэшируемые. Кэширование возникает в случае, когда клиент сохраняет предыдущие ответы сервера. Таким образом, если эта информация потребуется вновь, тот же самый путь можно проделать, основываясь на уже сохраненных данных. Возможность кэширования определяется наличием self-descriptive сообщений, так как, у клиента есть гарантия, что все важные сведения содержатся в одном ответе. Исключается фактор случайности при кэшировании лишь части сообщения.
Многоуровневая «слоеная» система означает, что помимо клиента и сервера во взаимодействии могут принимать участие другие компоненты. То есть в системе может быть больше одного слоя. Но при этом каждый компонент может взаимодействовать лишь с ближайшим к нему слоем. Таким дополнительным компонентом может быть прокси, он передает HTTP-запросы серверам или другим прокси. Это может быть полезно для распределения загрузки и проверки безопасности. Прокси выступает в роли сервера для привязанного к нему клиента, когда тот отправляет запрос, и в качестве клиента, когда транслирует его серверу.
Другой дополнительный компонент – gateway, переводящий HTTP-запрос в другой протокол, передает его, и затем, переводит ответ обратно в HTTP. Клиент может распознавать его как стандартный сервер. Вариант применения gateway – когда системе нужно скачать файл с FTP-сервера.
Кодировка по запросу – единственное необязательное условие во всей этой истории. Оно заключается в возможности сервера отправлять клиенту выполнимый код. Это то, что можно наблюдать на примере метки
<script>
в HTML. Когда документ HTML загружен, браузер автоматически извлекает JavaScript с сервера и реализует его на месте.Подводя итоги, можно сказать, что система RESTful – это любая сеть, отвечающая условиям, оговоренным Филдингом. Она удобна для многих процессов, масштабируема под большое число пользователей и компонентов и адаптивна к изменениям. Мы рассмотрели ее на примере того, как World Wide Web становится RESTful при взаимодействии браузеров и пользователей. REST описывает лишь теоретические принципы управления информацией, и веб сегодня в некоторых моментах до этой идеальной картины не дотягивает.
iiShrimp
habrahabr.ru/company/hexlet/blog/274675
bromzh
Плюс, есть и так куча статей и переводов на эту тему:
habrahabr.ru/post/181988
habrahabr.ru/post/144011
habrahabr.ru/post/144259
и т.д.
Ничего нового в RESTful не появилось, так что статья немного опоздала.