Данная статья давно назревала в моей голове, но совсем в ином формате.
Прочитав последние несколько неуклюжих статей на тему WEB-сервисов (например: http://habrahabr.ru/blogs/development/108973/) и применения в них REST технологии, решил что настало время все-таки откинуть лень, выделить время и написать «переформатированную» в своей голове статью.
Итак, кратко, что Вы найдете в статье и кому она будет полезна:
— новичкам, которые интересуются или планируют написать WEB-сервис для проекта
— профи вряд ли найдут что-то новое для себя
— общая идеология REST
— применение CRUD в WEB-сервисах
— принципы KISS при построении раутеров
— лучшие практики
— немного пиара ;)
— ссылки, литература
С чего начать решать вам, я порекомендую сперва дочитать статью, затем еще немного погуглить, выпить чашечку чаю/кофе/нужное_подчеркнуть, разложить мысли по полочкам и затем приступать к созданию вашего эй-пи-ай.
Что же такое REST *(1)?
REST — это “Representational State Transfer”, другими словами — представление данных в удобном для клиента формате, под клиентом мы подразумеваем клиентское ПО из модели client <-> server.
В свою очередь веб-сервисы созданные с использованием протокола HTTP и принципов REST называются RESTful web service.
У непосвященного сразу же может возникнуть вопрос: зачем нужны подобные сервисы? Приведу простой пример на основе REST и OAuth технологий: у Вас есть аккаунт на gmail и аккаунт на dropbox. Дропбокс предлагает Вам дополнительное место за каждого приглашенного друга, однако писать письмо вручную и перебирать все адреса из адресной книги gmail — не просто нудно, но и долго. Дропбокс предлагает “давай, дружище, я сам импортирую контакты и разошлю приглашения”. Понятное дело, что никто из Вас не захочет давать свой пароль от ящика на гмыле дропбоксу. Тут в силу вступает “магия” RESTful веб-сервисов. Используя API (эй-пи-ай, а не “апи”, как многие привыкли произносить), дропбокс делает запрос к веб-сервису гугля, затем “отправляет” Вас на страницу авторизации гугля, таким образом вы вводите свой пароль в форме у гугла, гугл вас авторизует и дает знать (выдает access_token) дропбоксу об успешности auth-процесса (authentication). В конце концов, имея уникальный токен (access_token) и прикрепляя его к каждому запросу в API, дропбокс имеет возможность работать с Вашими персональными данными, не зная ничего ровным счетом о Вашем пароле.
Важно помнить, что REST — это не обязательно использование протокола HTTP, хотя и изначально архитектура разрабатывалась с применением именно HTTP. В REST может использоваться любой протокол прикладного уровня (application layer) для транспортировки данных.
При разработке RESTful веб-сервисов важно помнить о методологии CRUD *(2), что в расшифрованном переводе означает: создать-прочитать-изменить-удалить (create-read-update-delete).
Так как разработка веб-сервисов ведется с использованием HTTP протокола, то и использовать нужно его плюшки, а именно: используйте методы протокола для определения действия над ресурсом. В мире REST общеприняты следующие стандарты:
POST — create (создать)
GET — read (прочитать, получить)
PUT — update (изменить, обновить или создать, если не существует, иногда применяется и в таком варианте)
DELETE — delete (удалить)
Необходимо отметить, что PUT и DELETE сложно реализуемые методы и ввиду особенностей браузеров, данным методы реализовать “по-человечески” средствами AJAX на стороне клиента-браузера, к тому же еще и чтобы работало во всех браузерах, не представляется возможным. Поэтому принято данные методы использовать посредством “перегрузки” метода POST. Другими словами: Вы отправляете с POST-методом какую-нибуть зарезервированную переменную, например: http_method, с именем метода, который Вы перегружаете. POST + http_method=put — дает понять вашей серверной части, что клиент запросил PUT над ресурсом.
Для начала расшифруем KISS — keep it small and simple, для тех кто еще не понял — придерживайтесь простых и маленьких вещей, другими словами чтобы это было доступно и понятно каждому и легко запоминалось.
Чтобы получить данные от вашего веб-сервера, клиенту необходимо знать URL, по которому ему необходимо обратиться. О принципах “построения” этих самых универсальных ресурсных указателей и пойдет речь.
Первым делом определите базовый набор правил, который подходит Вашему сервису. Например, у себя в компании oDesk мы обозначили, что URI, база которых — /api, это ресурсы RESTful API. При желании свой эй-пи-ай, Вы можете вынести на отдельный субдомен, здесь стоит помнить о кросбраузерных запросах и других подводных камнях, которые Вам встретятся, даже при запросах “внутри” одного домена.
Следующим моментом будет создание раутера ресурса — адреса, по которому можно будет обратиться к данным. Отметим несколько моментов, которые считаются хорошей манерой при составлении адреса:
— разбиение на идиоматические группы: mc — message center ресурсы, team — коммандные ресурсы и тд
например: /api/mc/…
— версионирование
например: /api/mc/v1/…
— ясное название ресурса, к которому предоставляется доступ
например: /api/mc/v1/prefs/… — доступ к настройкам мессадж центра
— внесение персистентных данных под URL
например: /api/mc/v1/prefs/mydevelopersuid
— определение формата ответа: либо в названии урл-е раутера, либо в “системной” переменной
например: /api/mc/v1/prefs/mydevelopersuid.json — oDesk использует суффикс “.json” когда требуется ответ в формате JSON, .xml — в формате XML и тд.; /mc/v1/prefs/mydevelopersuid?tqx=out:json — так делает Гугль, в GDS; /api/json/mc/v1/prefs/mydevelopersuid — просто еще один возможный вариант, формат является частью раутера.
Здесь можно много и долго говорить, перечислю основные моменты:
— всегда предоставляйте возможность получения ответа в формате json. Так случилось, что в мире AJAX приложений JSON *(3) стал де-факто “стандартом” передачи данных между клиентской и серверной частью.
— используйте для авторизации проверенные и отработанные схемы
Не изобретайте свой самокат с использованием md5 подписей данных и прочего, доверьтесь профессионалам в области защиты данных. OAuth придумали за Вас, для него полно библиотек на разных языках — используйте эту мощь. Не хотите OAuth, попробуйте APIKeys как это реализовано у Flickr-а. Есть еще парочка вариантов — OpenID и другие, всех рассматривать не буду — суть я донес.
— не забывайте о https, там где это нужно
и, пожалуйста, не забывайте к документации к своему эй-пи-ай указывать, что ваш сертификат самописный, если он таковым является. Цените время коллег из соседнего цеха, чтобы они не искали баги в своих апликухах только потому, что там стоит проверка на валидность сертификата.
— никогда не “вываливайте” в ответе что-то невнятное: ошибки Вашего веб-сервера, фаталы, проблемы соединения с базой и тд. Все это должно обрабатываться Вашим RESTful веб-сервером и отдавать внятный ответ в запрошенном формате. Другими словами, предоставьте внятный error responding клиенту. Формат ответа и заголовки — это отдельная тема. Хорошей практикой считается отдача корректных HTTP статусов в соответствии с RFC 2616 *(4) и если статус позволяет отдавать тело сообщения — наличие краткого сообщения в теле. Некоторые предпочитают отдавать всегда статус “200 ОК” с телом, таким образом клиент должен всегда парсить сообщение и проверять тело на наличие в нем сообщения/тега об ошибке. Однозначной практики и общего мнения пока нет!
— пишите документацию к своему API, иначе эй-пи-ай безполезно :)
— и, наконец, изначально продумайте внутреннюю архитектуру RESTful веб-сервиса, логика должна быть едина для любого запрошенного формата, а преобразование данных должно производится для каждого формата отдельно. Это позволит Вам легко и быстро расширять Ваши раутеры при необходимости добавить новый стандарт отображения данных.
будучи основным разработчиком RESTful API в компании oDesk (API — developers.odesk.com — это пиар, берите, пользуйтесь на здоровье! :) ) и занимаясь REST сервисами длительное время, считаю, что было уместно поделиться базовыми знаниями в данном направлении. Верить или не верить мне — Ваше личное право, но все же глубоко надеюсь, что каждый прочитавший хоть малую но пользу для себя найдет, как минимум освежите знания ;)
Архитектура REST все еще оставляет много вопросов и не редко приводит к холиварам, не обессудьте если мое мнение в чем-то не совпало с Вашим.
P.S. статья охватывает только базовые аспекты и не претендует на детальную инструкцию, книгу и тд для создания веб-сервисов.
(1) http://en.wikipedia.org/wiki/Representational_State_Transfer
(2) http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
(3) http://en.wikipedia.org/wiki/JSON
(4) http://www.w3.org/Protocols/rfc2616/rfc2616.html
Литература: RESTful Web Services (Leonard Richardson, Sam Ruby), O'Reilly Media, Inc.
Yahoo REST Group: http://tech.groups.yahoo.com/group/rest-discuss/
Прочитав последние несколько неуклюжих статей на тему WEB-сервисов (например: http://habrahabr.ru/blogs/development/108973/) и применения в них REST технологии, решил что настало время все-таки откинуть лень, выделить время и написать «переформатированную» в своей голове статью.
Итак, кратко, что Вы найдете в статье и кому она будет полезна:
— новичкам, которые интересуются или планируют написать WEB-сервис для проекта
— профи вряд ли найдут что-то новое для себя
— общая идеология REST
— применение CRUD в WEB-сервисах
— принципы KISS при построении раутеров
— лучшие практики
— немного пиара ;)
— ссылки, литература
С чего начать решать вам, я порекомендую сперва дочитать статью, затем еще немного погуглить, выпить чашечку чаю/кофе/нужное_подчеркнуть, разложить мысли по полочкам и затем приступать к созданию вашего эй-пи-ай.
ОБЩАЯ ИДЕОЛОГИЯ
Что же такое REST *(1)?
REST — это “Representational State Transfer”, другими словами — представление данных в удобном для клиента формате, под клиентом мы подразумеваем клиентское ПО из модели client <-> server.
В свою очередь веб-сервисы созданные с использованием протокола HTTP и принципов REST называются RESTful web service.
У непосвященного сразу же может возникнуть вопрос: зачем нужны подобные сервисы? Приведу простой пример на основе REST и OAuth технологий: у Вас есть аккаунт на gmail и аккаунт на dropbox. Дропбокс предлагает Вам дополнительное место за каждого приглашенного друга, однако писать письмо вручную и перебирать все адреса из адресной книги gmail — не просто нудно, но и долго. Дропбокс предлагает “давай, дружище, я сам импортирую контакты и разошлю приглашения”. Понятное дело, что никто из Вас не захочет давать свой пароль от ящика на гмыле дропбоксу. Тут в силу вступает “магия” RESTful веб-сервисов. Используя API (эй-пи-ай, а не “апи”, как многие привыкли произносить), дропбокс делает запрос к веб-сервису гугля, затем “отправляет” Вас на страницу авторизации гугля, таким образом вы вводите свой пароль в форме у гугла, гугл вас авторизует и дает знать (выдает access_token) дропбоксу об успешности auth-процесса (authentication). В конце концов, имея уникальный токен (access_token) и прикрепляя его к каждому запросу в API, дропбокс имеет возможность работать с Вашими персональными данными, не зная ничего ровным счетом о Вашем пароле.
Важно помнить, что REST — это не обязательно использование протокола HTTP, хотя и изначально архитектура разрабатывалась с применением именно HTTP. В REST может использоваться любой протокол прикладного уровня (application layer) для транспортировки данных.
CRUD
При разработке RESTful веб-сервисов важно помнить о методологии CRUD *(2), что в расшифрованном переводе означает: создать-прочитать-изменить-удалить (create-read-update-delete).
Так как разработка веб-сервисов ведется с использованием HTTP протокола, то и использовать нужно его плюшки, а именно: используйте методы протокола для определения действия над ресурсом. В мире REST общеприняты следующие стандарты:
POST — create (создать)
GET — read (прочитать, получить)
PUT — update (изменить, обновить или создать, если не существует, иногда применяется и в таком варианте)
DELETE — delete (удалить)
Необходимо отметить, что PUT и DELETE сложно реализуемые методы и ввиду особенностей браузеров, данным методы реализовать “по-человечески” средствами AJAX на стороне клиента-браузера, к тому же еще и чтобы работало во всех браузерах, не представляется возможным. Поэтому принято данные методы использовать посредством “перегрузки” метода POST. Другими словами: Вы отправляете с POST-методом какую-нибуть зарезервированную переменную, например: http_method, с именем метода, который Вы перегружаете. POST + http_method=put — дает понять вашей серверной части, что клиент запросил PUT над ресурсом.
ПРИНЦИПЫ KISS ПРИ ПОСТРОЕНИИ РАУТЕРА
Для начала расшифруем KISS — keep it small and simple, для тех кто еще не понял — придерживайтесь простых и маленьких вещей, другими словами чтобы это было доступно и понятно каждому и легко запоминалось.
Чтобы получить данные от вашего веб-сервера, клиенту необходимо знать URL, по которому ему необходимо обратиться. О принципах “построения” этих самых универсальных ресурсных указателей и пойдет речь.
Первым делом определите базовый набор правил, который подходит Вашему сервису. Например, у себя в компании oDesk мы обозначили, что URI, база которых — /api, это ресурсы RESTful API. При желании свой эй-пи-ай, Вы можете вынести на отдельный субдомен, здесь стоит помнить о кросбраузерных запросах и других подводных камнях, которые Вам встретятся, даже при запросах “внутри” одного домена.
Следующим моментом будет создание раутера ресурса — адреса, по которому можно будет обратиться к данным. Отметим несколько моментов, которые считаются хорошей манерой при составлении адреса:
— разбиение на идиоматические группы: mc — message center ресурсы, team — коммандные ресурсы и тд
например: /api/mc/…
— версионирование
например: /api/mc/v1/…
— ясное название ресурса, к которому предоставляется доступ
например: /api/mc/v1/prefs/… — доступ к настройкам мессадж центра
— внесение персистентных данных под URL
например: /api/mc/v1/prefs/mydevelopersuid
— определение формата ответа: либо в названии урл-е раутера, либо в “системной” переменной
например: /api/mc/v1/prefs/mydevelopersuid.json — oDesk использует суффикс “.json” когда требуется ответ в формате JSON, .xml — в формате XML и тд.; /mc/v1/prefs/mydevelopersuid?tqx=out:json — так делает Гугль, в GDS; /api/json/mc/v1/prefs/mydevelopersuid — просто еще один возможный вариант, формат является частью раутера.
ЛУЧШИЕ ПРАКТИКИ
Здесь можно много и долго говорить, перечислю основные моменты:
— всегда предоставляйте возможность получения ответа в формате json. Так случилось, что в мире AJAX приложений JSON *(3) стал де-факто “стандартом” передачи данных между клиентской и серверной частью.
— используйте для авторизации проверенные и отработанные схемы
Не изобретайте свой самокат с использованием md5 подписей данных и прочего, доверьтесь профессионалам в области защиты данных. OAuth придумали за Вас, для него полно библиотек на разных языках — используйте эту мощь. Не хотите OAuth, попробуйте APIKeys как это реализовано у Flickr-а. Есть еще парочка вариантов — OpenID и другие, всех рассматривать не буду — суть я донес.
— не забывайте о https, там где это нужно
и, пожалуйста, не забывайте к документации к своему эй-пи-ай указывать, что ваш сертификат самописный, если он таковым является. Цените время коллег из соседнего цеха, чтобы они не искали баги в своих апликухах только потому, что там стоит проверка на валидность сертификата.
— никогда не “вываливайте” в ответе что-то невнятное: ошибки Вашего веб-сервера, фаталы, проблемы соединения с базой и тд. Все это должно обрабатываться Вашим RESTful веб-сервером и отдавать внятный ответ в запрошенном формате. Другими словами, предоставьте внятный error responding клиенту. Формат ответа и заголовки — это отдельная тема. Хорошей практикой считается отдача корректных HTTP статусов в соответствии с RFC 2616 *(4) и если статус позволяет отдавать тело сообщения — наличие краткого сообщения в теле. Некоторые предпочитают отдавать всегда статус “200 ОК” с телом, таким образом клиент должен всегда парсить сообщение и проверять тело на наличие в нем сообщения/тега об ошибке. Однозначной практики и общего мнения пока нет!
— пишите документацию к своему API, иначе эй-пи-ай безполезно :)
— и, наконец, изначально продумайте внутреннюю архитектуру RESTful веб-сервиса, логика должна быть едина для любого запрошенного формата, а преобразование данных должно производится для каждого формата отдельно. Это позволит Вам легко и быстро расширять Ваши раутеры при необходимости добавить новый стандарт отображения данных.
PR
будучи основным разработчиком RESTful API в компании oDesk (API — developers.odesk.com — это пиар, берите, пользуйтесь на здоровье! :) ) и занимаясь REST сервисами длительное время, считаю, что было уместно поделиться базовыми знаниями в данном направлении. Верить или не верить мне — Ваше личное право, но все же глубоко надеюсь, что каждый прочитавший хоть малую но пользу для себя найдет, как минимум освежите знания ;)
Архитектура REST все еще оставляет много вопросов и не редко приводит к холиварам, не обессудьте если мое мнение в чем-то не совпало с Вашим.
P.S. статья охватывает только базовые аспекты и не претендует на детальную инструкцию, книгу и тд для создания веб-сервисов.
ССЫЛКИ*
(1) http://en.wikipedia.org/wiki/Representational_State_Transfer
(2) http://en.wikipedia.org/wiki/Create,_read,_update_and_delete
(3) http://en.wikipedia.org/wiki/JSON
(4) http://www.w3.org/Protocols/rfc2616/rfc2616.html
Литература: RESTful Web Services (Leonard Richardson, Sam Ruby), O'Reilly Media, Inc.
Yahoo REST Group: http://tech.groups.yahoo.com/group/rest-discuss/