REST сервисы
06.08.2014
|
AndrewVK |
Поскольку ряд товарищей спрашивает про сабж, попытаюсь поддерживать более менее актуальный список того что есть.
Общие моменты: все сервисы на данный момент на вход принимают параметры в виде form data (url для Get, тело запроса для Post), на выходе отдают JSON. Если результат с ошибками, возвращается HTTP код ошибки и JSON вида { field: "error_field", message: "error_message"}. Поле field, если оно есть, указывает на ошибку в конкретном входном параметре, либо содержит all, если ошибка к конкретному параметру не относится.
Аутентификация и сессия — общая с остальным сайтом, т.е. форма //Users/Login.aspx для логина, затем куки .RSDNAUTH и ASP.NET_SessionId.
Часть сервисов поддерживает ETag/If-None-Match и умеет возвращать 304, так что крайне желательно чтобы клиенты, отличные от браузеров, это использовали.
Для некоторых сервисов есть демки — http://rsdn.ru/rs/demo
Общие моменты: все сервисы на данный момент на вход принимают параметры в виде form data (url для Get, тело запроса для Post), на выходе отдают JSON. Если результат с ошибками, возвращается HTTP код ошибки и JSON вида { field: "error_field", message: "error_message"}. Поле field, если оно есть, указывает на ошибку в конкретном входном параметре, либо содержит all, если ошибка к конкретному параметру не относится.
Аутентификация и сессия — общая с остальным сайтом, т.е. форма //Users/Login.aspx для логина, затем куки .RSDNAUTH и ASP.NET_SessionId.
Часть сервисов поддерживает ETag/If-None-Match и умеет возвращать 304, так что крайне желательно чтобы клиенты, отличные от браузеров, это использовали.
Для некоторых сервисов есть демки — http://rsdn.ru/rs/demo
Сервис | Состояние | url | Метод | Параметры | Результат | Пример |
---|---|---|---|---|---|---|
Дерево навигации | Beta | //frames/navtreenodes | GET | string node — имя родительского узла. Для корня node=. | Все дочерние узлы, с учетом вложенности, до тех узлов, которые являются либо листьями, либо требуют загрузки по требованию. |
|
Сообщение RSDN Team | Production | //about/askteam | POST | string name, string email, string subj, string message | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Регистрация пользователя | Production | //account/doregister | POST | string login, string nick, string email, string pwd1, string pwd2, string recaptcha_challenge_field, string recaptcha_response_field | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Изменение емейла и пароля | Production | //account/dochangereg | POST | int? uid, string email, string oldPwd, string pwd1, string pwd2 | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Отправка нового сообщения | Alpha | //forum/<forum_name> | POST | string postingID, string forum, int msgID, string subject, string posterName, string password, string text, bool noSmile, string name, string tags, bool notifyAboutReplies | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Оценка сообщения | Production | //rs/message/<messageId>/rate/<rateType> | POST | string rateType, — Тип оценки: rate, smile или agree int messageID, int? value — Значение оценки. Для типа rate: 1-3, для типа agree: -4 согласен, 0 не согласен | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Удаление оценок | Production | //rs/message/<messageId>/rate | DELETE | int messageID, | пустой респонс с 204 кодом, если все хорошо, либо информацию об ошибке | |
Поиск профиля по подстроке | Production | //rsdnsearch/findauthor | GET | string name | Список идентификаторов и имен пользователей |
|
Получение списка топиков форума | Alpha | //rs/forum/<forum_name>/topics | GET | string forum, int? from, // По умолчанию 0 int? len // По умолчанию размер страницы из профиля | Список топиков в порядке убывания даты |
|
Получение списка ответов топика | Alpha | //rs/topic/<topicId>/replies | GET | int topicId | Список ответов в порядке возрастания даты |
|
Получение сообщения | Alpha | //rs/message/<messageId> | GET | int messageId, bool? formatted | Сообщение, включая его текст. В зависимости от значения formatted в качестве текста будет либо исходный код, либо готовый html для отображения |
|
Получение сообщений топика | Alpha | //rs/topic/<topicId>/messages | GET | int topicId, bool? formatted, int? from, int? len | Сообщения указанного топика, включая текст. В зависимости от значения formatted в качестве текста будет либо исходный код, либо готовый html для отображения |
|
06.08.2014 73 комментария |
AVK>Поскольку ряд товарищей спрашивает про сабж, попытаюсь поддерживать более менее актуальный список того что есть.
Спасибо! А можно сделать самое важное — получение списка тем в форуме, и собственно сообщений? Я тут на досуге пилю метро-клиент для винпланшетов, и пока приходится врукопашную html обрабатывать, что очень геморно — особенно в свете того, что вы постоянно меняете вёрстку...
K>Спасибо! А можно сделать самое важное — получение списка тем в форуме
Добавил.
AVK>Добавил.
Спасибо! С нетерпением жду вторую половину реквеста
AVK>>Добавил.
K>Спасибо! С нетерпением жду вторую половину реквеста
2/3. Ты про список ответов топика забыл. Но ты пока попробуй этот использовать.
AVK>2/3. Ты про список ответов топика забыл. Но ты пока попробуй этот использовать.
Не, я на выходных этим занимаюсь — в будни некогда сейчас, на работе дурдом.
K>Спасибо! С нетерпением жду вторую половину реквеста
Добавил получение ответов
AVK>Добавил получение ответов
Спасибо! Вопросы (смотрю на вывод http://rsdn.ru/rs/topic/5728024/replies ):
1. Нужен ParentId, чтобы можно было построить дерево.
2. Что такое "name" (который null) и "rowVersion"?
3. дата "createdOn" я так понимаю в тиках?
Ну и ещё нужна третья "половина"
K>1. Нужен ParentId, чтобы можно было построить дерево.
Упустил момент, поправлю
K>2. Что такое "name" (который null) и "rowVersion"?
У некоторых сообщений есть уникальное имя. Потом на них можно сослаться [#имя_сообщения].
RowVersion это равномерно возрастающее число, обновляющееся при каждом изменении сообщения.
K>3. дата "createdOn" я так понимаю в тиках?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
K>Ну и ещё нужна третья "половина"
Так вроде уже.
K>Спасибо! С нетерпением жду вторую половину реквеста
Добавил получение сообщений. С возможностью форматирования. И есть демка.
Не хочу показаться занудой, но это не совсем REST. Гораздо ближе к RPC-подобному API с JSON на выхлопе.
Н>Не хочу показаться занудой, но это не совсем REST. Гораздо ближе к RPC-подобному API с JSON на выхлопе.
Ну давай глянем вики:
Что из этого, кроме code on demand, принципиально не подходит?
AVK>Здравствуйте, Нахлобуч, Вы писали:
Н>>Не хочу показаться занудой, но это не совсем REST. Гораздо ближе к RPC-подобному API с JSON на выхлопе.
AVK>Ну давай глянем вики:
Мы академиев не кончали, но есть мнение, что ресурса "/f/ratemessage/{id}" (и подобных "/f/gettopics") не существует. А параметр "bool set" говорит о RPC-направленности. Как мне кажется, более тру было бы что-то типа "/forum/{name}/messages/{id}/rates" с операциями GET и POST (rate = 1|2|3|smile|upvote|downvote), а так же DELETE для "../rates/{rate}". С остальными "ресурсами" -- аналогично.
"Пустой респонс с 200 кодом" -- это 204. Всегда плеваться пятисотой ошибкой тоже не шибко канонично.
Ну и HATEOAS, но это совсем уже высший пилотаж.
Н>Мы академиев не кончали, но есть мнение, что ресурса "/f/ratemessage/{id}" (и подобных "/f/gettopics") не существует.
Почему ты так решил? Они вполне существуют, просто не все реализовано . Смутило get? Это просто для гарантии отсутствия конфликта с урлами страничек. Впрочем, уже переделано на /rs/forum/<forumname>/topics. <forumname>/topics — идентификатор ресурса.
Н> А параметр "bool set" говорит о RPC-направленности
Ничего подобного он не говорит, это тело POST запроса.
Н>. Как мне кажется, более тру было бы что-то типа "/forum/{name}/messages/{id}/rates" с операциями GET и POST (rate = 1|2|3|smile|upvote|downvote), а так же DELETE для "../rates/{rate}". С остальными "ресурсами" -- аналогично.
Это несложно переделать. Насчет DELETE так наверняка, заодно set выкинется.
Н>"Пустой респонс с 200 кодом" -- это 204.
В смысле?
Н> Всегда плеваться пятисотой ошибкой тоже не шибко канонично.
А оно там не всегда, я просто не описал. Бывает, как минимум, еще 400, 403 и 404.
Н>Ну и HATEOAS, но это совсем уже высший пилотаж.
Это в данном случае совсем без надобности.
Н>>Мы академиев не кончали, но есть мнение, что ресурса "/f/ratemessage/{id}" (и подобных "/f/gettopics") не существует.
AVK>Почему ты так решил?
Потому, что наличие глагола в имени ресурса делает его не совсем ресурсом.
Н>> А параметр "bool set" говорит о RPC-направленности
AVK>Ничего подобного он не говорит, это тело POST запроса.
Да, это тело RPC-стайл POST-запроса. Если бы происходила манипуляция ресурсами, то было бы ровно так, как я описывал:
Н>>"Пустой респонс с 200 кодом" -- это 204.
AVK>В смысле?
В смысле, по заветам HTTP каноничнее было бы в ответ на успешный POST-запрос возвращать не пустой ответ с HTTP 200, а пустой ответ с HTTP 204.
AVK>Это в данном случае совсем без надобности.
См. свой пассаж о "переделано". Если бы в результате переделок сервер научился бы выплевывать HTTP 301 для перенаправления со старых на новые URL'ы и эти URL'ы не формировались бы клиентом, а получались непосредственно из ответа, то жизнь клиентских приложений была бы тёплой и сухой.
И раз уж мы заговорили о REST и Stateless'ности -- может быть, подумать насчет какого-то альтернативного способа аутентификации и авторизации?
Н>Потому, что наличие глагола в имени ресурса делает его не совсем ресурсом.
Ну я так и подумал.
Н>См. свой пассаж о "переделано". Если бы в результате переделок сервер научился бы выплевывать HTTP 301 для перенаправления со старых на новые URL'ы и эти URL'ы не формировались бы клиентом, а получались непосредственно из ответа, то жизнь клиентских приложений была бы тёплой и сухой.
Пока никаких клиентских приложений для этих сервисов нет.
Н>И раз уж мы заговорили о REST и Stateless'ности -- может быть, подумать насчет какого-то альтернативного способа аутентификации и авторизации?
Может быть. Какого?
Н>>И раз уж мы заговорили о REST и Stateless'ности -- может быть, подумать насчет какого-то альтернативного способа аутентификации и авторизации?
AVK>Может быть. Какого?
Сам напрашивается Basic (и HTTPS, разумеется). Или что-то типа такого.
N>Пользуясь случаем хочу попросить, что бы мне пояснили, в чем отличие между REST и RPC.
Архитектурные подходы отличаются. В википедии довольно подробно расписано.
N>Пользуясь случаем хочу попросить, что бы мне пояснили, в чем отличие между REST и RPC.
http://rsdn.ru/forum/design/5520467.1
http://rsdn.ru/forum/design/5511534
http://rsdn.ru/forum/design/5008110.flat#5008110
Я так понимаю, "\/Date(1407754220)\/" — это издержки сериализации из дотнета. МС в своем репертуаре — если можно что-то сделать криво, не согласуясь ни с какими стандартами, то они это сделают.
Если это — миллисекунды, то достаточно
и указать в документации/комментариях (или не указывать ), что это миллисекунды
Самый правильный вариант был бы конечно ISO 8601
M>
M>Я так понимаю, "\/Date(1407754220)\/" — это издержки сериализации из дотнета. МС в своем репертуаре — если можно что-то сделать криво, не согласуясь ни с какими стандартами, то они это сделают.
Не сущетсвует стандарта по датам для Json.
ZB>Не сущетсвует стандарта по датам для Json.
Существуют стандарты отображения дат. Например, ISO 8601. Покажи мне стандарт на отображение даты в виде "/Date(int)/".
Существует и такой стандарт. Спору нет. Я думаю ты как программист справишься и распаршишь эту сложную строчку. Так как стандарта в json нет то все это отдано на откуп сериализатора.
К сведению..
M>>Существуют стандарты отображения дат. Например, ISO 8601. Покажи мне стандарт на отображение даты в виде "/Date(int)/".
ZB>Существует и такой стандарт. Спору нет. Я думаю ты как программист справишься и распаршишь эту сложную строчку.
В демках же есть:
Впрочем, и на ISO8601 переделать не сложно, только ее ж тоже парсить, js то либо число миллисекунд умеет, либо rfc2822.
AVK> Впрочем, и на ISO8601 переделать не сложно, только ее ж тоже парсить, js то либо число миллисекунд умеет, либо rfc2822.
Современный js тоже умеет ISO.
AB>Современный js тоже умеет ISO.
Ага, я уже нашел.
ZB>Существует и такой стандарт. Спору нет.
Спору нет, а он продолжает спорить
ZB>Я думаю ты как программист справишься и распаршишь эту сложную строчку.
Думаю я, как программист, предпочту использовать то, на что есть стандарты, а не то, что придумано левой задней пяткой создателей .NET'а
О чем спор вообще? «Не плодите сущности без необходимости» и KISS:
— во всем API нет полей, которые требуют парсинга
— поле created_at — это числовое поле, содержащее milliseconds since epoch
Что-то мне подсказывает, что представление числового поля в виде "\/.NET-специфичное(int)\/" — это, как минмиум, создание новой сущности
Ну а то, что в JSON нет стандарта на дату, это не отмазка:
— в JSON много на что нет стандарта
— вне JSON'а есть стандарты на отображение дат (и много на что еще)
— если поле можно представить простым (например, int вместо строки, которую надо парсить) или стандартным способом, но следут представлять это поле простым/стандартным способом
M>Думаю я, как программист, предпочту использовать то, на что есть стандарты, а не то, что придумано левой задней пяткой создателей .NET'а
Мне например всеравно. Я не понимаю твоего возмущения.
M>>Думаю я, как программист, предпочту использовать то, на что есть стандарты, а не то, что придумано левой задней пяткой создателей .NET'а
ZB>Мне например всеравно. Я не понимаю твоего возмущения.
Есть стандарт для отображения даты (ну или просто миллисекунды как целое число). Зачем использовать нестандартное и никем не поддерживаемое отображение?
M>Думаю я, как программист, предпочту использовать то, на что есть стандарты
Стандартов на дату в JSON нет. В JSON вообще все очень плохо со стандартами. Хочешь стандарты — лучше использовать XML, там все качественно детализовано и есть XSD.
M>, а не то, что придумано левой задней пяткой создателей .NET'а
Еще раз — поменять — не проблема.
AVK>Стандартов на дату в JSON нет. В JSON вообще все очень плохо со стандартами.
Есть полно стандартов, которые можно и нужно использовать Для дат — ISO 8601, для стран и языков ISO 3166 и ISO 639-1/2, для IP-адресов RFC-1918, для банковских аккаунтов ISO 13616 и 9362 и так далее и тому подобное (это из тех, что только мы используем постоянно). Не описывать же все эти стандарты в стандарте JSON'а?
AVK>Хочешь стандарты — лучше использовать XML, там все качественно детализовано и есть XSD.
Что-то мне подсказывает, что половины из того, что я написал выше, в XSD не указано
M>>, а не то, что придумано левой задней пяткой создателей .NET'а
AVK>Еще раз — поменять — не проблема.
\o/
Круто!
А можно добавить получение всех сообщений выбранной темы? А то тут некоторые темы за 700 ответов переваливают, делать 700 запросов как-то не хочется...
I>А можно добавить получение всех сообщений выбранной темы? А то тут некоторые темы за 700 ответов переваливают, делать 700 запросов как-то не хочется...
http://rsdn.ru/ws/janusat.asmx
AVK>Здравствуйте, ionoy, Вы писали:
I>>А можно добавить получение всех сообщений выбранной темы? А то тут некоторые темы за 700 ответов переваливают, делать 700 запросов как-то не хочется...
AVK>http://rsdn.ru/ws/janusat.asmx
А через новый REST нельзя будет?
I>А через новый REST нельзя будет?
А зачем?
AVK>Здравствуйте, ionoy, Вы писали:
I>>А через новый REST нельзя будет?
AVK>А зачем?
Ну мне, например, больше нравится читать сообщения когда они сразу развёрнуты. Дело вкуса
I>Ну мне, например, больше нравится читать сообщения когда они сразу развёрнуты. Дело вкуса
Так подгружай по мере скроллинга.
AVK>Здравствуйте, ionoy, Вы писали:
I>>Ну мне, например, больше нравится читать сообщения когда они сразу развёрнуты. Дело вкуса
AVK>Так подгружай по мере скроллинга.
Это можно, но всё равно хотелось бы батчинга. Иначе слишком уж много запросов придётся делать, а это медленно.
Я правильно понял что подразумевается что приложение показывает WebView с формой пользователь авторизируется и я потом получаю эти куки или ручной POST тоже работает и там нет нкиаких Cross Site Request Forgery (CSRF)?
ZB>Я правильно понял что подразумевается что приложение показывает WebView с формой пользователь авторизируется и я потом получаю эти куки или ручной POST тоже работает и там нет нкиаких Cross Site Request Forgery (CSRF)?
Ручной пост тоже работает.
а вот для этой страницы http://rsdn.org/forum/mainlist запроса нет?
Q>а вот для этой страницы http://rsdn.org/forum/mainlist запроса нет?
Нет. А нужно?
Очень хочется
rs//forum/messages?uid={0}&startDate={1}&endDate={2}"