От переводчика:
Я впервые попробовал перевести статью такого объёма и IT-тематики, с радостью прочту ваши комментарии и замечания. Что же касается самой статьи: я не согласен с автором как минимум потому, что, по сути, он заменяет REST на… REST (!!!), но немного в другом обрамлении. Однако, не смотря на то, что в статье преподносится много очевидных вещей, мне она показалась достойной обсуждения на Хабре.
Почему Вам стоит похоронить эту популярную технологию
Если за последние 10 лет Вы читали резюме веб-разработчиков, то Вам простительно думать, что RESTful API — это некое божественное дарование, сошедшее к нам с небес. REST API используется повсюду, даже маркетологи постоянно упоминают о нём в материалах, предназначенных сугубо для руководства или персонала.
Так на сколько всё же хороша идея REST API? Перед тем как мы разберемся с этим вопросом, давайте посмотрим откуда растут корни…
Данная технология стала популярной, когда она была подробно описана и представлена Роем Филдингом в его докторской диссертации под названием Architectural Styles and the Design of Network-based Software Architectures в 2000 году. Рой известен своими вкладами в развитие веба, в особенности HTTP.
REST — это стиль архитектуры программного обеспечения для построения распределенных масштабируемых веб-сервисов. Рой выступал за использование стандартных HTTP методов так, чтобы придавать запросам определённый смысл.
Таким образом, данные HTTP-запросы будут иметь различный смысловую нагрузку в REST:
Выше только некоторые виды запросов, а вот весь их список: CONNECT, DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT, TRACE. Если вы даже не слышали о некоторых из них — не беда, так как есть методы, которые практически никогда не поддерживаются ни клиентским, ни серверным приложением.
Рой также утверждал, что HTTP-коды ответов помогут в определении смысла самих ответов. Существует около 38 кодов ответа и ниже вы можете увидеть их список. Названия некоторых я немного сократил для удобства:
Итак, одна транзакция по такому API будет состоять, как минимум, из следующего:
Многие положительно отнеслись к такой парадигме и стали использовать её в разработке веб-сервисов с использованием HTTP. Это и есть то, что мы называем RESTful API.
Кстати, транзакция может быть более сложной и причины этому мы еще обсудим. Однако мы опустим те усложняющие факторы, которые связаны с сетями и кешированием, так как эти вопросы актуальны и для других технологий.
REST является отличным механизмом для многих вещей, например, таких как получение контента, и он отслужил нам верой и правдой почти 20 лет. Однако, настало время раскрыть глаза и признать, что концепция RESTful API является одной из худших идей, когда-либо существовавших в веб-разработке. Нет, я не спорю, Рой — отличный парень и, конечно же, у него было множество классных идей… Тем не менее, я не уверен, что RESTful API попадает в их список.
Вскоре мы посмотрим на другое, более правильное решение для построения API, но, перед тем как сделать это, нам следует понять 5 главных проблем RESTful API, которые делают его дорогим, уязвимым к ошибкам и неудобным. Начнём!
Вряд ли кто-то задумывался над тем почему эта технология называется именно «RESTful», а не «RESTpure»? (прим. переводчика: pure — чёткий, понятный) А потому что никто не может определиться с тем, что из себя представляют все методы запроса, коды ответа, тела и т.д.
Например, когда мы должны использовать код 200 ОК? Можем ли мы использовать его для подтверждения успешного апдейта записи, или нам стоит использовать код 201 Created? Судя по всему, нужно использовать код 250 Updated, однако его не существует. И еще, кто-нибудь может объяснить что означает код 417 Expectation failed?! Кто-нибудь кроме Роя, конечно.
Словарь HTTP методов и кодов слишком расплывчатый и неполный, чтобы прийти наконец к единым определениям. Нет никого, если я не ошибаюсь, кто нашел единый, общий порядок и призвал остальных его соблюдать. То, что подразумевается под 200 ОК в одной компании может обозначать вовсе иную информацию в другой, что делает обсуждаемую технологию непредсказуемой.
Если бы это было единственной проблемой, то я, наверное, смирился бы и продолжал писать RESTful API по сей день. Однако, наш список только раскрывается…
Даже если бы мы решили первую проблему, то столкнулись бы со следующей, практической: большинство клиентских и серверных приложений поддерживают не все коды ответа и, собственно, глаголы, означающие HTTP-методы. Например, большинство браузеров имеют ограниченную поддержку PUT и DELETE.
Как же мы с этим справляемся? Одним из способов является вставка глагола, обозначающего нужный метод, в отправляемую форму. Это значит, что в данном случае запрос включает в себя:
Ситуация с кодами ответа не лучше. Разные браузеры (и серверные приложения тоже) часто понимают эти коды по-разному. Например, получив код 307 Temporary redirect, один браузер может позволить пользовательскому скрипту рассмотреть этот ответ и отменить действие до его выполнения. Другой браузер может просто напросто запретить скрипту делать что-либо. На самом деле, единственными кодами, обработки которых можно не бояться, являются 200 ОК и 500 Internal server error. В остальных же случаях поддержка ответов варьируется от «довольно хорошей» до «просто ужасной». Именно по-этому нам часто приходится дополнять тело ответа кодом, который мы на самом деле подразумевали.
Даже если мы всё же смогли бы согласовать всё вышеописанное, а еще магическим образом пофиксили всё подключённое к интернету, но не приспособленное к REST программное обеспечение — мы всё равно столкнёмся с очередной проблемой.
Словарь, состоящий только из HTTP методов и кодов ответа, является слишком ограниченным для эффективной передачи и приёма разнообразной информации, необходимой всем приложениям. Представьте, что мы создали приложение, из которого мы хотим отправить клиенту ответ «render complete». К сожалению, мы не можем сделать это с помощью HTTP кодов, так как, во-первых, такого кода не существует, а во-вторых мы не можем его создать, так как HTTP — не расширяемый. Минутка разочарования. Думаю нам снова придётся вставлять то, что мы подразумеваем в тело ответа.
Также проблема в том, что у нас не один словарь, у нас их три! Коды ответов — это числовые значения (200, 201, 500), которые отличаются от представления методов запроса (GET, POST, PUT и т.д.), а тело ответа и вовсе в формате JSON. Выполнение REST транзакций — это как отправка письма на английском языке в Китай и получение оттуда ответа морзянкой. Все эти сложности являются крупным источником путаницы и ошибок. Вот мы и перешли к следующей глобальной проблеме: дебаггинг.
Если Вы когда-то работали с REST API, то Вы наверняка в курсе, что его почти невозможно дебажить. Для того, чтобы понять то, что происходит во время транзакции, нам приходится просматривать сразу 7 мест:
Так вот теперь у нас не только два сильно ограниченных словаря, так еще и 7 разных точек в которых может крыться ошибка. Единственное, что могло бы еще более усугубить ситуацию — это если бы технология REST была полностью привязана к одному протоколу и было бы невозможно использовать какой-либо другой канал связи. Собственно, так и есть, и это — наша следующая большая проблема!
RESTful API в дребезги разбивает один из фундаментальных законов о хорошей связи: содержимое сообщения должно быть абсолютно независимо от канала передачи. Их смешивание — это путь к сплошной путанице.
Постоянное переплетение HTTP протокола и передаваемой информации полностью лишает нас возможности переноса RESTful API на другие каналы связи. Портирование RESTfulAPI с HTTP на какой-либо другой протокол передачи данных требует полного распутывания и реструктуризации информации из семи разных точек, о которых мы говорили ранее.
К счастью, есть хорошее решение, которое позволяет избежать либо минимизировать все проблемы RESTful API. Встречайте!
JSON-pure API справляется с большинством проблем, которые мы только что рассмотрели.
JSON-pure API появилось в следствии осознания разработчиками того факта, что RESTful API не особо дружелюбно к браузерам и самим разработчикам. Разделение сообщения и способа передачи делает JSON-pure API быстрым, надежным, простым в использовании, портировании и поиске ошибок. Сегодня, если нам понадобится, например, использовать API Твиттера, то мазохисты выберут RESTful API. Остальные же обратятся к JSON-pure API, или, как его еще называют, «Web API».
За последние десять лет меня не раз просили использовать RESTful вместо JSON-pure. Крайний раз, когда мне чуть было не пришлось поддерживать RESTful API, был в 2011 году. К моему счастью, бэк-енд команда согласилась параллельно с RESTful запустить JSON-pure API, просто перенеся все свои методы и коды в JSON.
Спустя несколько месяцев все мои знакомые, ранее использовавшие RESTful, перешли на JSON-pure, осознав, что это гораздо удобнее.
Оригинал статьи: mmikowski.github.io/
Автор: Michael S. Mikowski
Я впервые попробовал перевести статью такого объёма и IT-тематики, с радостью прочту ваши комментарии и замечания. Что же касается самой статьи: я не согласен с автором как минимум потому, что, по сути, он заменяет REST на… REST (!!!), но немного в другом обрамлении. Однако, не смотря на то, что в статье преподносится много очевидных вещей, мне она показалась достойной обсуждения на Хабре.
Почему Вам стоит похоронить эту популярную технологию
RESTful api — это чудесно, ведь так?
Если за последние 10 лет Вы читали резюме веб-разработчиков, то Вам простительно думать, что RESTful API — это некое божественное дарование, сошедшее к нам с небес. REST API используется повсюду, даже маркетологи постоянно упоминают о нём в материалах, предназначенных сугубо для руководства или персонала.
Так на сколько всё же хороша идея REST API? Перед тем как мы разберемся с этим вопросом, давайте посмотрим откуда растут корни…
Откуда вообще взялся REST?
Данная технология стала популярной, когда она была подробно описана и представлена Роем Филдингом в его докторской диссертации под названием Architectural Styles and the Design of Network-based Software Architectures в 2000 году. Рой известен своими вкладами в развитие веба, в особенности HTTP.
Так что же такое RESTful API?
REST — это стиль архитектуры программного обеспечения для построения распределенных масштабируемых веб-сервисов. Рой выступал за использование стандартных HTTP методов так, чтобы придавать запросам определённый смысл.
Таким образом, данные HTTP-запросы будут иметь различный смысловую нагрузку в REST:
- GET /object/list
- POST /object/list
- PUT /object/list
Выше только некоторые виды запросов, а вот весь их список: CONNECT, DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT, TRACE. Если вы даже не слышали о некоторых из них — не беда, так как есть методы, которые практически никогда не поддерживаются ни клиентским, ни серверным приложением.
Рой также утверждал, что HTTP-коды ответов помогут в определении смысла самих ответов. Существует около 38 кодов ответа и ниже вы можете увидеть их список. Названия некоторых я немного сократил для удобства:
Итак, одна транзакция по такому API будет состоять, как минимум, из следующего:
- Метод запроса, например, GET
- Путь запроса, например, /object/list
- Тело запроса, например, форма
- Код ответа, например, 200 ОК
- Тело ответа, например, данные в формате JSON
Многие положительно отнеслись к такой парадигме и стали использовать её в разработке веб-сервисов с использованием HTTP. Это и есть то, что мы называем RESTful API.
Кстати, транзакция может быть более сложной и причины этому мы еще обсудим. Однако мы опустим те усложняющие факторы, которые связаны с сетями и кешированием, так как эти вопросы актуальны и для других технологий.
На самом деле RESTful API довольно ужасно
REST является отличным механизмом для многих вещей, например, таких как получение контента, и он отслужил нам верой и правдой почти 20 лет. Однако, настало время раскрыть глаза и признать, что концепция RESTful API является одной из худших идей, когда-либо существовавших в веб-разработке. Нет, я не спорю, Рой — отличный парень и, конечно же, у него было множество классных идей… Тем не менее, я не уверен, что RESTful API попадает в их список.
Вскоре мы посмотрим на другое, более правильное решение для построения API, но, перед тем как сделать это, нам следует понять 5 главных проблем RESTful API, которые делают его дорогим, уязвимым к ошибкам и неудобным. Начнём!
Проблема №1: До сих пор нет общего согласования того, что такое RESTful API
Вряд ли кто-то задумывался над тем почему эта технология называется именно «RESTful», а не «RESTpure»? (прим. переводчика: pure — чёткий, понятный) А потому что никто не может определиться с тем, что из себя представляют все методы запроса, коды ответа, тела и т.д.
Например, когда мы должны использовать код 200 ОК? Можем ли мы использовать его для подтверждения успешного апдейта записи, или нам стоит использовать код 201 Created? Судя по всему, нужно использовать код 250 Updated, однако его не существует. И еще, кто-нибудь может объяснить что означает код 417 Expectation failed?! Кто-нибудь кроме Роя, конечно.
Словарь HTTP методов и кодов слишком расплывчатый и неполный, чтобы прийти наконец к единым определениям. Нет никого, если я не ошибаюсь, кто нашел единый, общий порядок и призвал остальных его соблюдать. То, что подразумевается под 200 ОК в одной компании может обозначать вовсе иную информацию в другой, что делает обсуждаемую технологию непредсказуемой.
Если бы это было единственной проблемой, то я, наверное, смирился бы и продолжал писать RESTful API по сей день. Однако, наш список только раскрывается…
Проблема №2: Словарь REST поддерживается не полностью
Даже если бы мы решили первую проблему, то столкнулись бы со следующей, практической: большинство клиентских и серверных приложений поддерживают не все коды ответа и, собственно, глаголы, означающие HTTP-методы. Например, большинство браузеров имеют ограниченную поддержку PUT и DELETE.
Как же мы с этим справляемся? Одним из способов является вставка глагола, обозначающего нужный метод, в отправляемую форму. Это значит, что в данном случае запрос включает в себя:
- Метод HTTP запроса, например, POST
- Адрес запроса, например, /object/list
- Метод, который мы на самом деле подразумеваем, например, DELETE
- Тело запроса, например, данные из формы
Ситуация с кодами ответа не лучше. Разные браузеры (и серверные приложения тоже) часто понимают эти коды по-разному. Например, получив код 307 Temporary redirect, один браузер может позволить пользовательскому скрипту рассмотреть этот ответ и отменить действие до его выполнения. Другой браузер может просто напросто запретить скрипту делать что-либо. На самом деле, единственными кодами, обработки которых можно не бояться, являются 200 ОК и 500 Internal server error. В остальных же случаях поддержка ответов варьируется от «довольно хорошей» до «просто ужасной». Именно по-этому нам часто приходится дополнять тело ответа кодом, который мы на самом деле подразумевали.
Даже если мы всё же смогли бы согласовать всё вышеописанное, а еще магическим образом пофиксили всё подключённое к интернету, но не приспособленное к REST программное обеспечение — мы всё равно столкнёмся с очередной проблемой.
Проблема №3: Словарь REST недостаточно насыщен
Словарь, состоящий только из HTTP методов и кодов ответа, является слишком ограниченным для эффективной передачи и приёма разнообразной информации, необходимой всем приложениям. Представьте, что мы создали приложение, из которого мы хотим отправить клиенту ответ «render complete». К сожалению, мы не можем сделать это с помощью HTTP кодов, так как, во-первых, такого кода не существует, а во-вторых мы не можем его создать, так как HTTP — не расширяемый. Минутка разочарования. Думаю нам снова придётся вставлять то, что мы подразумеваем в тело ответа.
Также проблема в том, что у нас не один словарь, у нас их три! Коды ответов — это числовые значения (200, 201, 500), которые отличаются от представления методов запроса (GET, POST, PUT и т.д.), а тело ответа и вовсе в формате JSON. Выполнение REST транзакций — это как отправка письма на английском языке в Китай и получение оттуда ответа морзянкой. Все эти сложности являются крупным источником путаницы и ошибок. Вот мы и перешли к следующей глобальной проблеме: дебаггинг.
Проблема №4: RESTful API очень трудно дебажить
Если Вы когда-то работали с REST API, то Вы наверняка в курсе, что его почти невозможно дебажить. Для того, чтобы понять то, что происходит во время транзакции, нам приходится просматривать сразу 7 мест:
- Метод HTTP запроса, например, POST
- Адрес запроса, например, /object/list
- Метод, который мы на самом деле подразумеваем (в теле запроса), например, DELETE
- Собственно, тело запроса, например, данные из формы
- Код ответа, например, 200 ОК
- Код, который мы подразумевали (в теле ответа), например, 206 Partial Content
- Собственно, тело ответа
Так вот теперь у нас не только два сильно ограниченных словаря, так еще и 7 разных точек в которых может крыться ошибка. Единственное, что могло бы еще более усугубить ситуацию — это если бы технология REST была полностью привязана к одному протоколу и было бы невозможно использовать какой-либо другой канал связи. Собственно, так и есть, и это — наша следующая большая проблема!
Проблема №5: Как правило, RESTful API привязаны к протоколу HTTP
RESTful API в дребезги разбивает один из фундаментальных законов о хорошей связи: содержимое сообщения должно быть абсолютно независимо от канала передачи. Их смешивание — это путь к сплошной путанице.
Постоянное переплетение HTTP протокола и передаваемой информации полностью лишает нас возможности переноса RESTful API на другие каналы связи. Портирование RESTfulAPI с HTTP на какой-либо другой протокол передачи данных требует полного распутывания и реструктуризации информации из семи разных точек, о которых мы говорили ранее.
К счастью, есть хорошее решение, которое позволяет избежать либо минимизировать все проблемы RESTful API. Встречайте!
Шаг вперёд: JSON-pure API
JSON-pure API справляется с большинством проблем, которые мы только что рассмотрели.
- Использует только один метод для передачи данных — обычно POST для HTTP и SEND в случае использования Web Sockets
- Механизм передачи и содержимое запроса полностью независимы. Все ошибки, предупреждения и данные передаются в теле запроса, в формате JSON
- Используется лишь один код ответа, чтобы подтвердить успешную передачу, обычно это 200 ОК
- Механизм передачи и содержимое ответа полностью независимы. Все ошибки, предупреждения и данные передаются в теле ответа, в формате JSON
- Гораздо проще дебажить, ведь все данные находятся в одном месте в легко-читаемом формате JSON
- Легко перенести на любой канал связи, например, HTTP/S, WebSockets, XMPP, telnet, SFTP, SCP, or SSH
JSON-pure API появилось в следствии осознания разработчиками того факта, что RESTful API не особо дружелюбно к браузерам и самим разработчикам. Разделение сообщения и способа передачи делает JSON-pure API быстрым, надежным, простым в использовании, портировании и поиске ошибок. Сегодня, если нам понадобится, например, использовать API Твиттера, то мазохисты выберут RESTful API. Остальные же обратятся к JSON-pure API, или, как его еще называют, «Web API».
За последние десять лет меня не раз просили использовать RESTful вместо JSON-pure. Крайний раз, когда мне чуть было не пришлось поддерживать RESTful API, был в 2011 году. К моему счастью, бэк-енд команда согласилась параллельно с RESTful запустить JSON-pure API, просто перенеся все свои методы и коды в JSON.
Спустя несколько месяцев все мои знакомые, ранее использовавшие RESTful, перешли на JSON-pure, осознав, что это гораздо удобнее.
Оригинал статьи: mmikowski.github.io/
Автор: Michael S. Mikowski
Ununtrium
Автор хотел сделать провокацию в духе «Node.js is a cancer», но недотянул.
Аргументы в духе
настолько убоги, что даже комментировать нечего.
Не понимаю, зачем переводить какой-то бред. В англоязычном сегменте его уже засмеяли.
Encircled
Почему сразу бред то? Некоторые аргументы, конечно, высосаны из пальца. Но отсутствие спецификации и полная привязка к транспортному протоколу весьма весомые (для некоторых проектов).
lair
Понимаете, привязка к транспортному протоколу — это особенность REST. Для определенных ситуаций это достоинство, для определенных — недостаток. Окей, да.
Но эта особенность не делает REST, как подход, «ложью». Это всего лишь один из плюсов или минусов, который надо учитывать при выборе технологии.
(скажем, формально SOAP тоже не зависит от транспорта. А теперь скажите мне, сколько раз в своей жизни вы видели SOAP, реализованный не поверх HTTP?)
Encircled
Типичный заголовок для привлечения внимания, я не говорил что он мне нравится :)
Несколько раз встречал JMS. В общем, привязка к HTTP может быть критической в случаях интеграции с разнородными системами, либо, например, если планируется поддержка WebSockets.
lair
Так и аргументация под стать заголовку.
Знаете, в случае веб-приложений (и веб-сервисов) я еще ни разу не видел, чтобы интегрируемые системы были гомогенными.
Encircled
Добро пожаловать в кровавый интерпрайз :)
lair
Угу, «кровавый интерпрайз».
Один российский банк: DB/2 — .net over MS SQL.
Одно российское федеральное ведомство: .net — BizTalk — Lotus — (три разных имплементации SOAP на Java) — 1С.
Encircled
Поясню про интерпрайз. Я имею в виду не гомогенные системы, а часто изменяющиеся требования и требуемая (тавтология...) гибкость и полиморфность решений.
lair
… и как это говорит за/против REST? Да никак, в общем-то.
Encircled
Это говорит против использования REST в интерпрайз
lair
Каким образом? REST — очень гибкая парадигма, и, скажем, версионирование ему дается легче, чем SOAP.
Впрочем, в enterprise лучше всего, по моему опыту, работают шины сообщений.
mayorovp
lair
Если не секрет, какие именно технологии?
mayorovp
IBM WebSphere MQ (кстати, если кто-то будет выбирать MQ — ни в коем случае не выбирайте WebSphere! — там клиент под .NET уродский)
lair
WCF и биндинг или напрямую работа с очередью?
mayorovp
Работали напрямую, пока я не завернул эту радость в WCF :) Правда, биндинг MQ остался недописанным, потому что из-за особенностей разбиения приложения на слои пришлось пересылать полученные из MQ сообщения между слоями через HTTP.
Ходят слухи, что в 2016 году нам выделят еще несколько логических адресов на шине — и тогда про HTTP можно будет забыть.
lair
Почему-то я так и думал…
Ununtrium
Как уже заметили ниже: кто-то говорит что REST надо использовать везде? В подавляющем кол-ве проектов «переносить канал связи» не нужно.
Encircled
Я это и писал
Ununtrium
Хотите секрет открою? Для некоторых проектов не подходит Javascript. Жду статью от вас «Javascript — большая ложь».
Encircled
Да вы издеваетесь? Мне НЕ понравился эта статья, мне НЕ нравятся желтые заголовки. Я утверждаю лишь то, что 2 аргумента из статьи «не бред», как написал кто-то выше.
Ununtrium
Ок, поясняю:
1) Отсутствие спецификации компенсируется гайдами от разных компаний/людей. Типа как тут недавно от Яндекса.
2) Привязка к транспортному протоколу — это сама суть REST, осознанный шаг. Идея в том, что HTTP очень популярен, поэтому проще привязаться, чем городить абстракции. И вообще он в основном для конечного пользователя, нежели для интеграций.
Chikiro
Зачем методологии спецификация? Это же набор принципов и советов для создания проектов под определенные задачи. А у проекта уже и спецификация будет.
KReal
Ну так «Node.js is a cancer» же)
arvitaly
-
dannote
Основная проблема RESTful в том, что каждый раз при создании нового API фактически заново создается транслятор HTTP-to-SQL. Зачастую выходит так, что сам API имеет реляционный характер (
/users/1
,/users/messages
), в коде приложения используется ORM, а потом снова используется реляционная модель. Особенно нелепо это выглядит в приложениях, которые делают только самые примитивные CRUD операции.Есть, например, проект HTSQL, в котором на базе HTTP строится мощный язык запросов практически со всеми часто используемыми возможностями SQL, который напрямую транслируется в весьма оптимальный запрос на SQL. Для nginx (openresty) есть модуль ngx_drizzle, который умеет асинхронно отправлять запросы в MySQL и модуль rds_json, который в потоковом режиме строит из результатов JSON. Т. е. самое простое API можно создавать прямо в config-ах nginx как-то так:
Конечно, помимо таких простых запросов часто нужна дополнительная бизнес-логика, но часть задач можно уже сейчас переложить на БД. Например, для небольших проектов на уровне БД можно делать авторизацию с помощью недавно появившегося в PostgreSQL row-level security.
В общем, нужно переосмыслять идею REST, а не плодить одинаковые решения с одинаковыми архитектурными ошибками.
lair
Ээээ, а OData?
dannote
Во-первых, OData хоть и открытый стандарт, все его нормальные серверные реализации написаны под .NET.
Во-вторых, он довольно монструозный и имеет легкий Microsoft-овский налет.
lair
Ну провалились, и что? Это не отменяет того факта, что подход жизнеспособен. Возможно, ему просто не нужны стандарты в таком количестве?
Ну и да, вам разумно напомнили, что за REST далеко не обязательно стоит реляционная БД, так что ваш пойнт сам по себе не очень валиден.
Ununtrium
Насчет ngx_drizzle: Какие молодцы, выстроили свой протокол (если это можно так назввать) поверх HTTP, а сами даже про идемпотентность не слышали (будем инсерты в базу через GET делать, ага).
dannote
Это не протокол поверх HTTP, почитайте повнимательнее. Это просто модуль, делающий запросы к MySQL (или Drizzle, для которого он изначально писался) асинхронно и выдающий данные в формате RDS, которые следующим модулем по цепочке (например, rds_json или rds_csv) уже непосредственно преобразуются в ответ. Этот модуль написан человеком из CloudFlare и вполне себе production-ready. Читать данные из POST-запроса можно, например, с помощь модуля form-input-nginx. Есть еще большой список того, что нужно для идеального полноценного API, но база для этого уже готова.
Ununtrium
P.S.
Почитайте про CQRS, что-ли.
dannote
В приведенной вами цитате я не настаиваю на какой-то конкретной парадигме, а всего лишь константирую факт и привожу примеры. С приципом CQRS я знаком и понимаю, что не так может быть с API, представленном в виде исключительно CRUD-операций.
dannote
P.S., небольшая опечатка, имел ввиду
/users/1/messages
vedenin1980
А в чем проблема? Скажем в Java сериализация/десериализация json в java объекты делается буквально одной строчкой, причем никто не мешает добавить этим java объектам теги JPA и сразу напрямую сохранять их в ORM. Зачем тут придумывать трансляторы SQL? И не вижу у SOUP и других технологий каких-то преимуществ при сохранении через ORM.
dannote
Вопрос не в том, насколько легко это делается и тем более, не в том, на какой платформе. Вопрос в том, насколько много лишних действий происходит под этой кучей красивых оберток. В предложенном вами варианте вообще безумная цепочка: автоматическая десериализация JSON в POJO, потом автоматическая сериализация из POJO в подстроку SQL-запроса и наконец автоматическое построение SQL-запроса. Я первоначально хотел обратить внимание, что с учетом проблем object-to-relational городить relational-to-object-to-relational для простых задач просто абсурдно.
vedenin1980
Предложите другие варианты, проблема в том что когда пытаются сделать попроще, вроде простой генерации SQL запросов руками, потом получают проблемы c sql injection. Да, в любом самом простом решении все равно используется десятки оберток, обертки для работы с сокетами, обертки для работы с базой данных и т.д.
vedenin1980
Эээ, то есть вы считаете куча оберток проекта HTSQL чем-то лучше? Обертка на HTTP, обертка на JSON, обертка в виде своего языка запросов, обертка над SQL, причем все обертки свои кастомные да ещё все в одном проекте (явное нарушения принципа одной обязанности). Уж, лучше взять какое-нибудь nosql хранилище, вроде mongoDb и сохранять json из Rest'a прямо напрямую в монгу.
dannote
Я упомянул HTSQL как отличную концепцию, а не как конкретную реализацию. Правильно было бы, на мой взгляд, сделать парсер путя с параметрами в URI в самой БД как отдельный модуль и для ряда запросов вообще обходить парсер SQL, просто поставив БД в upstream на кеширующий сервер. Это не всегда хорошее и не всегда универсальное решение, но практика показывает, что SQL нередко бывает bottleneck-ом. Если что, я сейчас потихоньку пишу такой модуль для MySQL, работая напрямую с InnoDB и со многими потенциальными проблемами знаком.
vedenin1980
Честно говоря не понял этой отличной концепции HTSQL, ни один разумный человек на даст делать прямые SQL запросы любому пользователю прямо в браузере, потому что это просто мечта хакера. Если вы готовы дать кому-то возможность делать прямые SQL запросы в вашу базу данных, так дайте ему удаленный доступ и возможность делать нормальные SQL запросы, зачем тут «посредник» со своим языком запросов?
Какой модуль-то? Сделать из SQL базы данных noSQL? А зачем? Честных noSQL баз данных существует огромное количество от key-value хранилищ до сохранения полноценных документов, а SQL база данных всегда будет хуже эмулировать noSQL.
Парсер путя, как вы назвали, не имеет большого смысла. Если вы готовы дать постороннему прямой доступ к SQL запросам в вашей базе данных, намного проще дать ему удаленный доступ и возможность слать нормальные SQL запросы, благо практически любой SQL сервер такое позволяет. Имя базы данных и таблицы намного лучше придумывания каких-то своих путей.
dannote
Нет.
Я не говорил о том, что запросы должны идти без какой-либо авторизации.
Нет.
ACID.
Модуль memcached к MySQL видели?
Просто посмотрите примеры и предстаьте себе нативную реализацию прямо в БД. Это не NoSQL в обычном понимании. Все тоже самое что с SQL, только другой язык запросов, который можно передавать в БД как есть, без лишних промежуточных представлений и строить на его основе execution plan.
Имя таблицы и так уже есть в путях во многих фреймворках.
vedenin1980
Не так важно авторизация или нет, возможность динамически задавать SQL запросы всегда небезопасна и её стоит разрешать либо собственным сотрудникам, либо очень хорошо проверенным клиентам. Скажем, вы возвращаете select * from users where user_id = 87333, где id это тот самый пользователь, а он берет и меняет запрос select * from users where user_id = 1 и получает все данные администратора. Да, есть способы ограничить права в SQL базах, но не всегда они работают по отдельным записям и всегда можно ошибиться и дать прав больше чем нужно.
Именно поэтому прямой доступ к своему SQL серверу ни одна нормальная компания клиентам не даст, для того и придумали Rest и т.п. технологии. А вы по сути предлагаете давать прямой доступ из-за чего такая технология ограничена внутренней сетью компании и ничем не лучше просто удаленного доступа к базе данных.
lair
А где вы видите relation-to-object?
dannote
REST во многих его реализациях — это как раз и есть попытка сделать HTTP реляционным, я написал об этом в первом комментарии.
vedenin1980
1) Никогда таких попыток не встречал, можете привести пример? Вообще-то, json это как раз объект, например это родной объект для javascript, а по правилу не хранения состояния Rest'a ссылки на другой json вообще-то не очень корректны, откуда тут реляционность-то?
2) Те кто пытается сделать Rest реляционным — сами себе злобные буратины,
3) В любом случае json это объект (даже если он какую-то реляционность эмулирует), поэтому json в ORM, это преобразования объекта в объект,
dannote
Практически в любом API, где имеется какая-то связность между объектами («сообщения пользователя», «комментарии к новости»), выстраиваются отношения один-к-одному и один-ко-многим. Пример — GitHub API, да и практически любой другой API в стиле Sinatra. Ссылки между объектами — это не хранение состояния. Под хранением состояния, например, подразумевается привязка результатов и контекста выполения к текущей сессии. От этого отказываются, поскольку при масштабировании проще всего, удобнее и надежнее создавать одинаковые ноды и не задумываться о переносе контекста. JSON — это не объект, это синтаксическая конструкция, описывающая объект, причем далеко не самым лаконичным способом. И если вы не понимаете, например, что именно происходит при сериализации/десериализации JSON в POJO, не понимаете смысл идеи RESTful, и, наконец, не понимаете, что я хотел донести, не нужно, пожалуйста, заводить спор.
vedenin1980
Это не реляционность, это сохранение id другой сущности, реляционность появится только при загрузки в реляционную базу данных. Сам по себе id другой сущности не может создать ссылку, нужно либо отправить объект на которой ссылка в одном json'е, либо поднимать его из реляционной базы данных. Так что в json'е как в любом объекте может быть только «эмуляция» ссылочности не более того.
Она есть конечно, но не уровне Rest'a и json'a, для json'a все равно текстовое поле или поле хранящее id другой сущности, связность исключительно на уровне бизнес модели.
В Javascript например ничего не происходит, JSON это и есть объект которые может содержать даже методы javascript'a.
JSON в javascript это объект, которые может содержать даже методы javascript'a
dannote
А вот и нет, происходит. Только на этапе трансляции, а не интерпретации. А при десериализации в Plain Old Java Object либо дергается небыстрый Reflection API, либо на лету осуществляется кодогенирация, что не лучше. Нравится блуждать в мире абстракций — пожалуйста. Вот тут, например, люди запускают три интерпретатора JS (JavaScriptCore, JavaScriptCore и V8) и шлют данные между ними alert-ом через pipe в этом самом JSON и ничего, 1500 звезд на GitHub-е.
vedenin1980
Вы знаете разницу между Java и JavaScript'ом? Какой Reflection API?
либо программисты используют не DOM парсер, если так важна скорость
dannote
А вот DOM здесь вообще при чем?
vedenin1980
Вы не знаете что парсеры не ограничиваются DOM (или Data Binding) моделью? В том же jackson'e есть аж три вида парсера, если вопрос в памяти и производительности, то нормальный программист использует Streaming парсеры.
И повторяю вопрос какая связь между Java и JavaScript'ом, в последнем ответе я говорил только о JavaScript'e?
dannote
Я вас только что процитировал, вы первоначально писали про де-/сериализацию JSON в Java. А вот о Document Object Model вообще ни слова не было и к сериализации данных ни в Java, ни в JavaScript-е это не имеет никакого отношения.
Что значит — какая связь?
dannote
Если что, пример с PhantomJS был просто как наглядная демонстрация безумного нагромождения абстракций, сопоставимого с вашим «одной строчкой на Java».
dannote
Ладно, если ваша аргументация уже скатилась до намеков, что, мол, я не понимаю разницы между Java и JavaScript, пора поставить точку.
К вашему сведению, я читал спецификацию ECMAScript 6 целиком и в свое время правил и писал байткод для JVM руками и ооочень хорошо чувствую разницу между этими двумя языками и их средами исполнения.
Ну а насчет вас я для себя уже все выяснил.
vedenin1980
Тью, а какое это отношение это имеет к проф.деятельности? Я мог бы понять если бы вы мое CV откопали и рассказывали что у вас-то в сто раз больше опыта. Действительно, смысла такого дискуссии с переходом на личности явно нет, тем более что вы не отвечаете ни на один неудобный вам вопрос.
lair
Это если вы мыслите отношениями.
При моделировании этого домена вполне можно решить, что комментарии к новости (я просто не знаю, что вы понимаете под сообщениями пользователя) — это часть агрегата (здравствуй, DDD) «новость», и это классическое отношение композиции (которое классическими РСУБД адекватно не моделируется).
lair
Что вы вкладываете в понятие «реляционным» во фразе «сделать HTTP реляционным», и в каких реализациях REST вы это видели?
dannote
Я тщетно пытаюсь донести мысль, что URL в REST теряет свое первоначальное значение становится и не идентификатором, а языком запросов, в чем-то подобным SQL (работающим в рамках реляционной модели), а значит, пора уменьшать прослойку кода. Особенно это актуально для single-page-applications, которые большую часть данных тянут на лету с сервера в том виде, в котором они представлены в базе данных и не стремятся выбраться за границы CRUD.
Пример скинул выше.
lair
Вы ошибаетесь дважды. Во-первых, URL как был, так и остается локатором ресурса, и если для какого-то ресурса (например, коллекции) логично добавить параметры запроса, влияющие на локацию (например, фильтр), это все еще не делает URL языком запросов.
А во-вторых, что важнее, наличие языка запросов не означает реляционной модели. Нереляционная модель, и особенно документо-ориентированные хранилища здесь существенно ближе к аналогии.
Какой именно? GitHub?
robert_ayrapetyan
Бизнес-логика в триггерах — это похлеще пресловутого define true false…
dannote
В триггерах — да, но кое-какие вещи сделать как view можно себе позволить.
smileonl
Как же меня раздражают подобные жёлтые заголовки для статей.
Я читал эту статью пару недель назад и даже там до последнего думал что автор шутит ) Но нет — всё серъёзно.
Shakirok
Я тоже не люблю такие провокационные заголовки, но статья называлась так в оригинале.
vaniaPooh
Одну ногу я побрила…
crmMaster
А второй нет — я ее уже давно отстрелила.
Envek
Поздравляю автора — он изобрёл SOAP, только на основе JSON, а не XML. Всё то же самое — отвязка от транспортного протокола и перенос всей логики в сам протокол.
На самом деле все эти ужасы преувеличены. Браузеры спокойно поддерживают метод DELETE (мы из приложения на Angular.js спокойно шлём запросы DELETE и PATCH пачками) и не очень стандартные коды ответов (мы так же широко используем 422 Unprocessable Entity, чтобы показать, что запрос был семантически некорректным и транзакция произведена не была и надо смотреть в тело ответа — там будут сообщения об ошибках).
jrip
Браузеры то да, а вот серверное нестандартное не факт.
Если смотреть стандартный случай, клиент + api, то обычно все ок, но на практике часто бывают взаимные взаимодействия с различными сервисами, а везде реализовывать RESTful задолбаешься.
VolCh
Они их поддерживают только в JS, в html — нет
lair
А как вы себе представляете работу с REST API из HTML? Они в общем-то и не для этого придуманы.
hmspns
Как по мне, самый большой недостаток REST — высокие затраты времени на разработку. Если API предоставляется через SOAP (так поступает большинство крупных компаний банковского, страхового и других B2B секторов), достаточно взять кодогенератор, который из WSDL файла сгенерирует прокси классы и всё, через 3 минуты ты можешь делать запросы, при этом особенности транспорта тебя не волнуют. Круче всего это реализовал Microsoft в своём WCF, где через конфигурационный файл можно выбрать любой транспорт, от http(s) до MSMQ (включая tcp и named pipes). WSDL файл и SOAP автоматически генерируются на основе кода.
А REST, вот я так в толк и не возьму, какие у него основные плюсы. Меньше данных передаётся? В мире единицы сайтов, для которых экономия на траффике в таких масштабах превысит стоимость разработки REST.
Всё структурно? Да хз, как бы да, но реально дебажить приходится смотря на все 7 мест, указанных в статье. И опять же, если следовать RESTful, то те моменты, которые через RPC решаются за один запрос, через RESTful за кучу. Не понимаю я его смысл как «эталона», короче.
lair
… а потом ты внезапно выясняешь две вещи.
(а) реализации SOAP на этой и той стороне отличаются (например, вы по-разному трактуете время без указания часового пояса)
(б) в WSDL (точнее, XSD) описаны далеко не все детали формата, а в паре мест стоит
xs:any
.(ц) авторизация… авторизация? авторизация, мать ее!
Real life stories.
А что такого в «стоимости разработки REST»? Чем она радикально выше, чем разработка под SOAP?
Конкретный пример можно?
(а) простота использования из браузерного кода
(б) опора на существующую HTTP-инфраструктуру (например, кэширование)
(ц) «встроенная» мультиформатность
(д) более очевидная семантика
hmspns
Если API кривой, то не важно REST он, не REST, проблемы всё равно будут.
не понял вас тут
Ну, как минимум, надо свой транспорт писать. Формирование JSON, запрос к удалённому компьютеру, считывание ошибок, протоколирование, парсинг JSON обратно в объекты. В реализации SOAP майкрософта это всё идёт из коробки, вызвал функцию на сгенерированном прокси-классе, обратно получил результат, случилась ошибка — вывалился exception. Это работает прозрачно, как будто всё происходит в рамках одного процесса.
Конкретный пример — работа с транзакциями, описание разницы есть тут: habrahabr.ru/post/131343
Тут согласен, но это делает его в основном пригодным только для фронтэнда. Причём в рамках одного домена, из-за ограничения на кроссдоменные запросы.
lair
Конечно, просто в этом месте понимаешь, что — внезапно — SOAP не решает. А иногда, что хуже, мешает, потому что формировать его руками тяжело и сложно.
В HTTP есть простые и понятные способы аутентификации и авторизации. В SOAP с этим все весело, особенно когда вы делаете межвендорную (например, .net — Java) интеграцию.
Http-клиент, в любой разумной платформе из коробки.
У того же Microsoft для всего этого давно есть обертка (
HttpRequestMessage/HttpResponseMessage
) с расширениями.До первой проблемы, особенно проблемы формата 400 Bad Request без объяснений.
Если под транзакциями вы понимаете ACID, то в RPC с этим все тоже плохо. А если под транзакцией вы понимаете бизнес-операцию, которая предполагает много внутренней логики, то в REST они прекрасно делаются.
Угу, а теперь давайте задумаемся, что мы не хотим писать два разных сервиса для веб-клиентов и мобильных клиентов, а после этого добавим сюда third-party. Вот, собственно, и вся интеграция для нормального веб-приложения.
CORS.
hmspns
Ну конечно SOAP не решает, разве я это где-то говорил?
На практике, обычно выделяют отдельный метод для авторизации, который возвращает токен и этот токен используется в последующих запросах, это не является проблемой.
Клиент то из коробки, но это не отменяет необходимость формирования JSON, запроса к удалённому компьютеру, считывания ошибок, протоколирования, парсинга JSON обратно в объекты. А клиент да, позволяет делать запрос не беспокоясь о TCP и нижележащих протоколах.
А REST тут чем лучше? Если тот же Bad Request без объяснений вываливается? Это вопрос качества реализации API, если она кривая, придётся мучиться.
Под транзакциями я понимаю ACID и не понимаю что там плохого.
Для B2C возможно, у B2B таких проблем обычно не стоит.
Вам не кажется, что мы с вами о разных вещах говорим? Моя позиция: REST переоценен, во многих ситуациях SOAP позволяет экономить время на разработке клиента, а в ряде случаев и сервиса. Вы с этим принципиально не согласны?
lair
Вот здесь:
Стандарты? WS-Security? Нет, не слышал. Вот в этом и проблема: каждый делает по-своему.
Вы, видимо, не в курсе:
Тем, что между вами и происходящим меньше уровней абстракции, проще понять, что происходит.
Распределенные транзакции плохо удаются любому протоколу, не важно, RPC это или SOAP. Это проблема распределенности, а не протокола.
С такой формулировкой — нет, не согласен. Во-первых, я не считаю, что REST переоценен. Во-вторых, SOAP, действительно, иногда позволяет экономить время на разработке клиента — но далеко не всегда. Чем сложнее сценарий использования, тем меньше эта экономия.
Что важнее, эта «экономия» — она по сравнению с самописным обменом. Если же вы будете сравнивать с любой другой устоявшейся парадигмой (messaging, REST), то выяснится, что различия более архитектурные, чем временные, и именно от архитектуры и надо плясать.
lair
Прошу прощения, читать «RPC или REST».
hmspns
Извините за бестактность, но вы русский язык знаете? В этом абзаце написано про то, что SOAP позволяет автоматически сгенерировать прокси классы, которые позволят сразу делать запросы не учитывая конкретных особенностей транспорта. Где вы тут увидели что SOAP решает?
А в REST значит всё стандартизировано? Ну-ну.
А у вас класс Product откуда взялся? Сами написали? Ну круто. Хорошо если там 3 поля, а как начинаешь работать со страховыми продуктами, то там мама не горюй какой объём и вложенность. Помнится, интегрировали мы одну страховую, расчёт туристического страхования (не самый сложный продукт), объём сгенерированного кода был за 3 000 строк. Сколько по КАСКО (сложный продукт) я даже думать не хочу. Для аналогичного продукта другой страховой компании, написанного как раз на REST, было затрачено около 70 человекочасов дополнительно на транспорт.
Обоснуйте
А SOAP и RPC — не архитектура? И что такое временные различия?
lair
В утверждении «позволят сразу делать запросы». В реальности это далеко не всегда так.
В REST не стандартизовано, но в REST безопасность делегирована на транспортный уровень, а там, в свою очередь, есть устоявшиеся практики. Разница в том, что в SOAP в половине случаев безопасность определяется сгенеренными прокси, а они могут уметь, а могут и нет. В качестве развлечения предлагаю вам добавить в WCF подписание сообщений по ГОСТу.
Конечно, нет. Тут есть два занятных нюанса.
Во-первых, REST не означает JSON. А как только мы берем в качестве формата xml, нам сразу доступен весь инструментарий от xsd.
Во-вторых, для JSON тоже есть схемы и генераторы.
Очень просто. RPC вообще (и SOAP в частности) не имеет транзакционной семантики, ее всегда добавляет какой-то дополнительный инструмент. Соответственно, когда вам нужна распределенная транзакция, вы добавляете координатор и соответствующие вызовы — и вам, по большому счету, пофиг, куда их добавлять.
SOAP и RPC (как и messaging или REST) — это парадигмы, между которыми есть крупные отличия, радикально влияющие на архитектуру решения.
А временные различия — это как раз то, о чем вы пишете, «технология А позволяет сэкономить время на разработке клиента».
hmspns
В этом утверждении говорится только о запросах, не о том, что REST решает. Это вы сами додумали.
Несомненно, иногда приходится приложить дополнительные усилия. Но если API спроектирован хорошо, все прокси-классы сгенерируются и запросы можно будет делать сразу. Но это не проблема SOAP, а кривых рук разработчиков API.
А что мешает использовать https для SOAP запросов? Что до практик, вы сами упоминали WS-Security. То что им не всегда следуют — не проблема SOAP, а кривизны рук разработчиков API. Это как машина, знаете, правила нарушает не она, а водитель.
Делал я подписание сообщений и ручную проверку сертификатов. Не по ГОСТу, а по AES, но с учётом того, что инфраструктура криптопровайдеров стандартизирована, а ГОСТовские провайдеры есть, не думаю что там будут особые сложности.
А в REST, кстати, это как-то очень просто делается? Там вроде только свелосипедить можно, https ГОСТ не особо уважает, насколько я знаю.
И что, есть реализации координаторов для REST?
Ну REST как бы больше ограничений накладывает. Тут и отсутствие состояний, и обязательное использование http, и жёстка завязка на предопределённые коды ответа и методы http. SOAP (simple object access protocol) и RPC (remote procedure call) по определению с этой стороны гораздо более гибкие.
lair
К сожалению, SOAP API чаще спроектирован плохо, чем хорошо. И частично это как раз следствие внутренней избыточности SOAP, а частично — разницы реализаций на разных сторонах.
Не знаю, что мешает. Но регулярно не используют.
… или неумения конкретного инструмента.
Вы же почему-то предложили не WS-Security, а «На практике, обычно выделяют отдельный метод для авторизации, который возвращает токен и этот токен используется в последующих запросах».
К сожалению, в .net она стандартизирована только до определенного предела, а дальше начинаются проблемы. Так что сложности и веселье там есть в полный рост (начиная с того, кстати, что WCF генерит некорректные с точки зрения XMLDSIG атрибуты).
Скажем так, в конкретном майкрософтовском WebAPI это делается существенно легче — просто в силу того, что транспортный уровень ближе и контролируемее, чем в WCF.
А что, есть реализации координаторов для SOAP?
Вы считаете, что в SOAP нет ограничений? Даже если мы берем самую базовую реализацию — вам нужно контролировать actions и структуру сообщения. В реальности почти всегда вам нужно больше — как минимум, безопасность — и дальше вы немедленно влетаете в то, как именно и какую вам надо делать. А еще, на «чистом честном» SOAP тяжело делать версионирование с одновременной поддержкой нескольких версий. Не невозможно, но тяжело.
И это только с одной стороны. А с другой стороны: вы считаете, что ограничения — это зло? А я так не считаю, я считаю, что они позволяют более строго формализовать архитектуру и уменьшить количество неопределенностей.
Вы почему-то считаете, что я считаю, что SOAP плохой, а REST — хороший. А я считаю, что каждый из них подходит для своей задачи, а для каких-то задач подходит что-то третье.
hmspns
Не я предложил, это чаще всего встречается в существующих API, которые мы к себе интегрируема.
Ну как бы да: msdn.microsoft.com/en-us/library/ff384250.aspx
Я так считаю? Вы же начали отвечать на мой комментарий, пытаясь прицепиться к каждому пункту.
lair
Вот вам и демонстрация «правильного дизайна API».
Это пока еще не SOAP, а WCF. С кем совместима эта реализация (насколько я понимаю, там WS-AT)?
vedenin1980
Зачем? Для таких вещей есть библиотеки, скажем в Java есть RestEasy для создания rest сервиса/клиента парой строчек и Gson/Jackson для сериализации JSON в Java объекты одной строчкой. В целом, сделать Rest сервис с нуля можно за несколько часов (включая доменную модель, простую бизнес обработку и теги сохранение данных в JPA), сделать аналогичный WSDL вряд ли получится быстрее.
Не поверите, но библиотек автогенерация классов в Rest тоже хватает. Все равно проблема не в подключении библиотек, а в корректной бизнес обработки полученных данных.
Так WSDL тоже кто-то должен сначала сделать. Когда вы пишите клиента к чужому SOUP вам WSDL дадут, а если надо написать самим все с нуля? К тому же далеко не всегда автогенерация из WSDL во всех ЯП работает сразу и без проблем.
А это много? Скажем в Java если я сделаю за 15 минут класс с сотней полей, а потом скажу IDEA сгенерить сетеры, гетеры, конструкторы, toString, hashcode, equals, javadoc'ки — у меня легко получится класс на 3 тыс. строк.
kr41
Основной плюс REST в том, что любой программист может взять свой любимый язык программирования и за пару часов написать на нем клиента к любому REST-сервису. В случае с RPC, если генератор прокси-классов для любимого языка кривой, то придется либо пилить напильником, либо использовать нелюбимый язык. У меня так было со Thrift 3 года назад. В Java он работал как часы, а в Python — баг на баге. Может быть сейчас и пофиксили, но желания использовать его с тех пор нету.
hmspns
Ну это же проблема не RPC, а конкретной реализации кодогенератора.
kr41
Нет, это как раз-таки проблема RPC, что без кодогенератора — никуда. Как принимается решение о том, что использовать? Например, на упомянутом мной проекте было так: бэкэнд — Java, фронтенд — Python. Вопрос: что используем для связки? Java-команда предлагает Thrift: «Вот, смотрите, он быстрый, есть binary-протокол и в документации написано, что Python поддерживается». Ок, соглашаемся. Пишем спецификации, генерируем код. Код — говно, но вроде работает. А потом проект начинает расти и начинаются первые баги. Выясняется, что binary протокол не умет работать с Unicode. Что некоторые классы почему-то не генерируются. И если посчитать сколько времени было убито на поиск багов, на допиливание генератора. А потом перевести это в деньги. А потом показать счет клиенту… Ну вы поняли.
Я не то чтобы против RPC. Просто у каждой технологии своя область применения. RPC хорош для внутреннего использования, где вы точно знаете на каких ЯП будут писаться клиенты, и что для них существует нормальный кодогенератор. REST же хорош для публичного API, тогда можно ограничиться хорошей документацией, по которой любой желающий сможет написать своего клиента на любом, даже самом экзотичном ЯП.
potan
Разработка и синхронизация с кодом на scala/java/c# файлов WDSL требует времени и сил. И специальных инструментов — синтаксис ужасен, лично я в vim я такое редактировать не способен.
Отладка RESTful-подобных интерфейсов как раз удобна, используя curl или powershell Invoke-RestMethod из командной строки.
hmspns
Не уверен, что использовать vim для разработки на C# хорошая идея, есть специализированные инструменты, типа студии (которая бесплатная в community edition), в которой таких проблем нет.
velvetcat
… и на свет появляется очередное го*но-API, состоящее из точащих наружу кишков го*но-приложения.
Извините за резкость, но API — это то, над чем надо очень, очень хорошо думать. И то, что в REST нельзя добавить 100500 разношестных методов на все случаи жизни с кучей побочных эффектов — это очень хорошо для публичных API.
lair
Да можно, можно в REST добавить кучу «методов», было бы желание. Всегда есть POST на произвольный адрес или с произвольным контентом (который REST не противоречит, хотя и предпочтительно его избегать).
Так что применение головы все же обязательно.
Chikiro
В REST нет кучи методов, а есть ресурсы. Не определились с ресурсами — начали гордить кучу костылей с произвольными адресами и произвольным контентом.
lair
Потому и кавычки.
Речь о том, что если не понимать методологию, то можно наплодить кривой API где угодно.
bogus92
JSON-RPC 2.0? Там еще и batch запросы можно делать.
zelyony
автор противопоставляет создание REST-запросов — через формирование урлов с параметрами и request-тела, а также разбор http-кодов и response-тела — простому JSON со всеми запросами, параметрами и кодами в удобоваримом виде одним текстом. в данном контексте с тем же успехом можно заменить JSON на XML. и вариант с JSON/XML выглядит более органичным и расширяемым.
и те, кто считает, что автор «тупит», не формируют ведь REST-запросы ручками, а используют всякие либки и фреймворки.
но если бы вам пришлось их формировать — без сторонних либок REST или SOAP — вы бы стали морочиться с полным HTTP-REST или простым HTTP-GET/POST и JSON/XML? другое дело, кто хочет писать велосипеды…
для JSON-pure тоже наверняка есть либки и фрейворки. косяк автора в том, что он их не разбирает на плюсы и минусы, а просто говорит, что RESTful — гамно. за что и закидался тухлыми яйцами.
много дыма из ничего.
lair
Конечно, стали бы. Намного проще отправить пустой запрос
DELETE uri
, чем формировать тело сообщения с командой и идентификатором.willson
Жду перевода статьи «JSONpure API — большая ложь», где главным аргументом против будет указана нетипизированность данных и хорошо если будет в качестве решения какой-нибудь edn, ато ведь и к XML вернемся, как расширяемой и самоописываемой обертке.
jonic
Отлично, теперь я знаю как называется то что я использую.
Shakirok
У меня была похожая реакция)
jrip
Проблема RESTful в том что мало кто делает именно точно RESTful, почти у всех какие-то особенности и оговорки.
Да и он далеко не все проблемы решает связанные с взаимодествие с API.
А еще вот есть Apache Thrift кстати, который решает больше проблем, немного в другой плоскости, но тоже по теме.
orcy
Выглядит как замаскированный личный наезд, что не очень приятно. RESTful все же показался многим полезной вещью для создания разного рода публичных и частных API без какого-либо сильного вендора за спиной, так что нельзя сказать что это «ложь» или что автор публикации сплоховал и придумал какую-фигню.
mikolalex
RESP был прекрасен по сравнению с подходами вроде SOAP своей stateless философией, и именно популяризацию такой философии я считаю основной заслугой REST'a. С другой стороны, использование протокола НТТР для описания семантики приложения — это ужасный рак, прокрустово ложе, в которое мы себя добровольно загоняем. Весь этот сыр-бор — из-за классической ошибки, называемой «смешение уровней абстракции», которая произошла с протоколом НТТР. этот прокотол описывает взаимодействие между узлом сети и ресурсом. Но разработчики НТТР решили также включить в набор статусов терминологию, которая относится к бизнес-логике конкретного приложения, и залезли таким образом на уровень выше, куда лезть не следовало. Я имею ввиду как статусы вроде Payment Required, так и более завуалированную ересь вроде Created(зачем такой ответ? Если запрос явно предполагал создание чего-либо, то достаточно ответа ОК, то есть, «все получилось»). Резюмируя, я бы сказал, что рест является удачным и еффективным подходом, построенным на ошибочной концепции.
Какой из этого выход? Таки использовать JSON-pure АРІ и иметь возможность точно описать всю специфическую для приложения логику, не только Payment Required, а и, скажем, Upgrade Account required, или Admin rights required, и что заблагорассудится.
mayorovp
Извиняюсь, но почему вы противопоставляете SOAP и stateless? Много веб-сервисов именно stateless и являются, более того — именно такие сервисы и рекомендуется делать.
mikolalex
Потому что rest — stateless, а soap — нет. Мне больше нравится stateless подход, и то, что rest его использует, я считаю большим плюсом rest'а.
Да, полностью согласен, а к чему вы повторили общеизвестный факт?
mayorovp
mikolalex
это популярное заблуждение, почитайте:
http://www.ibm.com/developerworks/library/ws-spmyths/
over HTTP или нет, значения не имеет.
REST же stateless по своему определению.
mayorovp
Все, что написано там, применимо и к REST тоже. Разница лишь в том, что в REST за такое будут бить по рукам, а при использовании SOAP — нет.
Но если вам нравится stateless подход — ничто не мешает использовать его совместно с SOAP.
mikolalex
Скажем так, в REST'е отсутствие состояния — краеугольный камень, и если это требование нарушено, возникает вопрос, а рест ли это, или рест-подобная поделка, которых сейчас очень много? В соапе использование состояния во многих случаях неизбежно и его отсутствие — это скорее исключение.
lair
Это в каких же случаях состояние в соапе неизбежно?
(я надеюсь, мы говорим про техническое состояние, а не бизнес)
Chikiro
По-моему, никто и не запрещает отвечать OK. Мне кажется коды ответа не конкретную ошибку отдают, а класс ошибоки, более подробную информацию и инструкции по дальнейшим действиям надо в теле ответа смотреть (а тем, кто пишет API, выводить их, а не скрывать).
voidnugget
Для того что бы решить проблемы упомянутые в статье — нужно использовать гипермедиа типы (hateoas).
Но там такой сыр-бор твориться…
* У Swagger'a, в этой роли, пока что ничего не получается, и поддержка довольно ужасна.
Alexeyco
Одно могу сказать — автор этой статьи достиг своей цели: бурление говен. Теперь и на Хабре. В общем-то, во время чтения меня сначала тоже подорвало, но читая дальше и дальше, я понял, что меня попросту троллят. И я успокоился…
Ununtrium
Теперь мнение невежд высказанное в письменной форме называется троллинг? :)
Alexeyco
Просто я не в курсе достижений автора (именно автора, к переводчику никаких претензий). Поэтому предположил лучшее из возможного.
forgotten
Такой срач стоит вокруг совершенно пустой статьи.
Достаточно заметить, что автор попросту не знает, что такое REST.
Да нет же! Использование стандартной номенклатуры методов и статусов — только часть REST, не самая важная (вообще-то можно строить REST-сервисы и не поверх HTTP). Важных ограничений четыре:
— клиент-серверная архитектура (в частности, клиента не заботит, на каких технологиях реализован сервер за счет унифицированного протокола)
— отсутствие состояний: все детали операции содержатся в самой операции; т.е. в парадигме REST нельзя сделать вот так:
DELETE /user/data
со взятием id юзера из куки. REST-клиент обязан отправить запрос вида
DELETE /user/{userid}/data
А куку использовать строго для проверки, имеет ли право этот юзер удалять данные {userid}
— управление кэшированием — методы, статусы и заголовки позволяют гибко кэшировать максимальный объём данных; в частности
GET /user/data — невозможно закэшировать, потому что id юзера знает только сервер
GET /user/{userid}/data — кэшировать уже можно
— многослойная архитектура — сервер может, не уведомляя клиет, проксировать по HTTP запрос дальше (что достижимо как раз за счет унифицированной работы с протоколом).
Ну и многочисленные фактические ошибки по ходу статьи не позволяют рассматривать её сколько-нибудь всерьёз
RFC2616: If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
Здесь я сломался и дальше не читал.
MuLLtiQ
Да троллинг это, причем весьма толстый
jrip
>>Достаточно заметить, что автор попросту не знает, что такое REST.
Простите, но вы тоже фигню всякую пишите :)
>>— клиент-серверная архитектура (в частности, клиента не заботит, на каких технологиях >>реализован сервер за счет унифицированного протокола)
Если взять тупо чистый http запрос, клиенту не пофигу что на сервре?
>>— отсутствие состояний: все детали операции содержатся в самой операции; т.е. в парадигме
>>REST нельзя сделать вот так:
>>DELETE /user/data
>>со взятием id юзера из куки. REST-клиент обязан отправить запрос вида
>>DELETE /user/{userid}/data
А кука у вас в чем так в этом случае принципиально от урла отличается? Так же на сервер уйдет в общем случае в заголовке.
>>А куку использовать строго для проверки, имеет ли право этот юзер удалять данные {userid}
Так вы перепутали куки с серверной сессией? Ну так в по идеалогии Restful нельзя сохранять состояние.
>>— управление кэшированием — методы, статусы и заголовки позволяют гибко кэшировать >>максимальный объём данных; в частности
>>GET /user/data — невозможно закэшировать, потому что id юзера знает только сервер
>>GET /user/{userid}/data — кэшировать уже можно
И только сервер знает, когда протухнет кеш, вообщем со стороны управлением кеша без разницы.
>>— многослойная архитектура — сервер может, не уведомляя клиет, проксировать по HTTP >>запрос дальше (что достижимо как раз за счет унифицированной работы с протоколом).
Очень много чего можно так проксировать, не уведомляя клиент, странный довод.
forgotten
> Простите, но вы тоже фигню всякую пишите :)
Ну я хотя бы множественное лицо второго рода настоящего времени глаголов отличаю от повелительного наклонения.
Писать — глагол первого спряжения, в окончаниях настоящего времени пишется «е».
> Если взять тупо чистый http запрос, клиенту не пофигу что на сервре?
Если у вас организована передача данных в виде, например, сериализованных PHP-объектов, то клиенту приходится знать, что на сервере работает PHP. REST-методология требует представлять операции в виде собственно HTTP-запросов так, чтобы семантика операции была понятна из самого запроса.
> А кука у вас в чем так в этом случае принципиально от урла отличается? Так же на сервер уйдет в общем случае в заголовке.
Тем, что URL не указывает конкретный ресурс, над которым выполняется операция. В семантике HTTP операция DELETE /user/data означает удаление всех данных всех юзеров.
> Ну так в по идеалогии Restful нельзя сохранять состояние.
Я именно это и написал.
> И только сервер знает, когда протухнет кеш, вообщем со стороны управлением кеша без разницы.
Интересное «без разницы».
GET /user/{userid} клиент может кэшировать по отдельность для каждого userid, и инвалидировать кэш также по отдельности (используя If-Modified-Since, например). GET /user кэшировать вообще нельзя.
> Очень много чего можно так проксировать, не уведомляя клиент, странный довод.
Нет, не очень.
Если у вас есть операция
GET /?method=шарах
И сервер проксирует её до другого гейтвея, она вполне может оказаться где-то по пути закэшированной и в реальности не выполниться. Эта схема может работать если и только если все промежуточные узлы понимают и правильно интерпретируют семантику HTTP.
forgotten
> множественное лицо второго рода настоящего времени
Тьфу, множественное число второго лица, конечно же.
jrip
>Ну я хотя бы множественное лицо второго рода
>настоящего времени глаголов отличаю от повелительного наклонения.
>Писать — глагол первого спряжения, в окончаниях настоящего времени пишется «е».
Чтож, подловили :) Хотя мы тут про Rest вроде?
>Если у вас организована передача данных в виде, например, сериализованных
>PHP-объектов, то клиенту приходится знать, что на сервере работает PHP.
Какие-то вы бредовые примеры приводите, я писал про сравнение Restfull и обычный просто http, но впрочем даже в таком бредовом примере, нет клиенту не надо знать что там PHP, надо только знать формат сериализации, а он строгий.
>REST-методология требует представлять операции в виде собственно
> HTTP-запросов так, чтобы семантика операции была понятна из самого запроса.
Каша какая-то. Как связана семантика операции и формат получаемых данных?
>> Ну так в по идеалогии Restful нельзя сохранять состояние.
>Я именно это и написал
Тогда причем тут куки вообще?
>Интересное «без разницы».
>GET /user/{userid} клиент может кэшировать по отдельность для каждого userid, и
> инвалидировать кэш также по отдельности (используя If-Modified-Since, например).
>GET /user кэшировать вообще нельзя.
В вашем первом странном примере без разницы.
>Нет, не очень.
>Если у вас есть операция
>GET /?method=шарах
>И сервер проксирует её до другого гейтвея,
>она вполне может оказаться где-то по пути закэшированной
>и в реальности не выполниться.
Ну и? Есть метод и он что-то получает, раз GET, вы позволили ему где-то закешироваться.
>Эта схема может работать если и только если все промежуточные
>узлы понимают и правильно интерпретируют семантику HTTP.
Так Rest то тут вообще причем?
forgotten
Абсолютно ни при чём, вы совершенно правы.
Chikiro
Можно, если у вас есть ресурс по адресу test.ru/user/data, url — всего лишь идентификатор ресурса, REST не навязывает никаких правил по именованию и иерархии.
shamanis
Ну не знаю, мне после мамонтообразного SOAP и такого-же JSON-RPC REST кажется наиболее лаконичным методом реализации API. По поводу дебага, например на Django можно отлично писать Unit-тесты, если вы пользуетесь rest_framework. Извините заранее, все комментарии не читал. Статья, имхо, вброс и скрытый пиар.
Tab10id
Удивлен что никто не написал про ограничения метода GET, в случаях каких-нибудь query-запросов частенько помещаются не все параметры и приходится, опять же, использовать POST.
dmitry_pavlov
Я согласен с автором статьи. Думаю самый хороший вариант с точки зрения разработчика — это уяснить суть RESTful сервисов, понять какие бывают типы запросов, какие из них реально поддерживаются, разобраться в кодах, в целом «подружиться» с каналом передачи протоколом HTTP и т.п. Все это даст понимание технологии и знания как правильно с ней работать. Дальше действительно удобней использовать только POST и с помощью JSON уже формировать удобную для себя структуру пакета сообщений, реализовывая по сути старый добрый request/response подход, который зарекомендовал себя давно и использовался почти во всех системах и технология сетевого взаимодействия. Надо заметить при этом, что в своих сообщениях разработчик может поддерживать принципы REST, введя свои типы сообщений для CRUD операций и поддерживая логику их обработки. HTTP в данном случае будет просто транспортом. Отвязка от канала передачи — это (опятьже согласен с автором) большой плюс.
lair
Не может. Использовать POST для чтения данных — противоестественно для REST.
jrip
А если при получении данных у нас ацкая куча фильтров и в GET мы не влезаем? :)
lair
Значит, у вас техническая проблема, для решения которой вам придется положить на семантику. Беда и печаль.
jrip
Это не проблема, а необходимость :)
И их может быть много разных, поэтому по факту Restful это лишь набор рекомендаций, которые далеко не во всех случаях вообще реально использовать.
lair
Не спорю. Но если вы их не используете — то у вас уже не REST (по крайней мере, в контексте данной операции/ресурса).
jrip
Ну в том то и прикол, я вот например не видел ни одного большого проекта, где реально REST, а не «ну почти REST». И все споры где что и как должно быть по канонам — они бессмысленны и выдают возможный недостаток опыта :)
lair
Почему же. Споры «как должно быть по канонам» имеют смысл, чтобы понимать, куда стремиться — и чтобы, если можно сделать правильно, делать правильно.
jrip
>Споры «как должно быть по канонам» имеют смысл, чтобы понимать, куда стремиться
Зачем спорить о том, что четко описано?
>если можно сделать правильно, делать правильно.
Правильно это понятие относительное, в абсолютном понимании правильно решенная задача — это задача выполняющая некие изначальные условия. Для того чтобы понять, что есть restful спорить смысла нет, достаточно почитать.
lair
Как видно из дискуссий — описано недостаточно четко, чтобы все понимали.
dmitry_pavlov
Верно. Это противоестественно для REST. Но речь как раз и идет о том, чтобы не сковывать себя ограничениями REST отвязать свою модель зваимодействия поверх HTTP. POST запрос в плане ограничений самый беспроблемный и имеет массу преимуществ с точки зрения программиста. Использовать его как транспорт для любых типов запросов — удобно. Семантику запроса в этом случае убираем в тело передаваемых JSON данных и используем POST паровоз для отправки наших запросов и получения ответов от сервера.
Принципы REST если они вам удобны и дороги — можно перенести и внутрь ваших сообщений, поджерживая все составляющие REST запроса — метод, ресурс, данные, код возврата и тп. При этом избавившись от душевных мук, когда в проекте рано или поздно все равно придется отступить от RESTful и сделать идеологический хак, потому что иначе не получается из-за ограничений RESTful сервисов :)
jrip
>Но речь как раз и идет о том, чтобы не сковывать себя ограничениями REST отвязать
>свою модель зваимодействия поверх HTTP. POST запрос в плане ограничений
>самый беспроблемный и имеет массу преимуществ с точки зрения программиста.
Вы теплое с мягким путаете. Если же вы просто имеете ввиду, что на REST надо забить и намутить свой велосипед, то это тоже подход не очень.
>Принципы REST если они вам удобны и дороги — можно перенести и
>внутрь ваших сообщений, поджерживая все составляющие REST запроса
А это еще хуже, когда REST называют то, что им не является и путают людей.
lair
Нельзя «перенести принципы REST внутрь сообщений», об этом и речь. Получите вы обычный RPC, коим много лет уже.
dmitry_pavlov
Верно. Но я не вижу проблемы в RPC. Давно зарекоммендовавший себя концепт.
lair
Не видите — и хорошо, ваше личное дело, может у вас и нет проблем. Только REST-ом не называйте.
dmitry_pavlov
Дао Вебсервиса. (Или да хватит же изобретать велосипеды!) — http://habrahabr.ru/post/75248/
lair
Угу. Уже сильно больше одного раза обсудили все проблемы SOAP, надо еще раз повторить?
dmitry_pavlov
Да нет. Я к тому, что глупо гнаться за понятием, когда занимаешься практической работой. Не вижу смысла навешивать ярлыки на технологии, принимать одну их них за священную корову и потом мучаться от ее недостатков в ежедневной работе. Это удел молодых программистов, которые пороху еще не нанюхались и собак съели мало :)
dmitry_pavlov
И хватит минусовать — это как-то глупо что ли. Моя точка зрения имеет такое же а то и большее право на существование по сравнению с вашей :)
lair
Архитектура (в том числе хорошая), поддерживаемость, тестируемость — это все «понятия». За ними тоже не надо гнаться?
Никто не считает REST священной коровой. Это конкретный подход с весьма конкретными ограничениями. Кому ограничения не нравятся — окей, пожалуйста, сколько угодно, можете не использовать, можете даже ругать и говорить, что другая технология лучше; но зачем называть то, что вы используете вместо REST — REST?
dmitry_pavlov
Да, тоже не надо гнаться. Любая идея, возведенная в абсолют — зло :) Архитектура — это выбранный способ устройства частей приложения и их взаимодействия. Может быть любой. Какой бы она ни была — это будет архитектура. Плохая она или хорошая — можно судить используя выбранные критерии. Поддерживаемость, тестируемость и прочие так нахываемые "-ilities" как раз и являются этими самыми криетриями. Подчеркну еще раз, что оценку архитектуры на «хорошесть» делают именно относительно выбранных криетериев, а не всех имеющихся в природе в принципе. Это важный момент. Выбор тех или или иных критериев обусловлен требованиями к приложению. Которые (обычно) обусловлены бизнес задачами (в случае коммерческого ПО по крайней мере).
Думаю мне удалось донести мысль о том, что стремление соответствовать какому-либо понятию, не имея обусловленной понятными причинами потребности в этом, а просто потому что так «правильно» — это глупость?
На счет самих слов «использовать REST» — не понимаю, зачем вы мне приписываете неясные формулировки, а потом возмущаетесь что я там что-то не так навал и асамозабвенно минусуете мои коментарии. Я четко сказал, что можно заимствовать концепцию («Принципы REST») и избавиться от многих ограничений данного подхода. Ну а что как называть — дело вкуса :) Тут следуется договориться о терминах перед тем как спорить.
REST — это не конкретная технология (реализация), а стиль архитектуры что ли… метод взаимодействия частей распределённого приложения в сети интернет.
При соблюдении (надо сказать довольно расплывчатых требований) та или иная реализвация вашего сервиса может быть с той или иной долей справедливости названа «RESTful» веб сервисом.
lair
Вы почему-то приравниваете «гнаться за идеей» к «возведено в абсолют». А зря.
Конкретно описанный вами подход (ввести свои типы сообщений, поместить семантику внутрь них, использовать только POST) противоречит противоречит концепции REST (например, пункту про кэшируемость). Поэтому я не понимаю, что вы собираетесь «заимствовать».
dmitry_pavlov
Кешируемость в ряде случаев — как раз относится к минусам, откоторых хочется избавиться.
Заимствовать (не дублировать полностью) основной концепт этого подхода и cделать удобную — обладающую необходимыми свойствами и характеристиками (в рамках выбранных критериев) — реализацию API. Я говорю об этом. И о том, что «RESTful webservices» напрасно возвели на пьедестал и холиворно бездумно стараются его придерживаться всегда и везде. Любая концепция хороша к месту.
Утомился я пререкаться. Думаю, продолжать не уже буду. Спасибо за дискуссию.
lair
Ага, а вы избавляетесь везде, и что-то говорите о возведении в абсолют.
Мне вот, все-таки, очень интересно, что же вы считаете «основным концептом» REST.