Комментарии 26
Прям ностальгия. В 2005-м писал свою реализацию и в нескольких проектах она до сих пор используется.
0
Особенности json-rpc:
— асинхронный, причём в одном соединении в обработке может висеть несколько запросов
— работа в режиме запрос->ответ, либо подписка->уведомления, причём подписываться может как клиент, так и сервер
— асинхронный, причём в одном соединении в обработке может висеть несколько запросов
— работа в режиме запрос->ответ, либо подписка->уведомления, причём подписываться может как клиент, так и сервер
0
НЛО прилетело и опубликовало эту надпись здесь
Я так и не понял чем плох REST. Не вижу разницы между:
host.ru/api + {«jsonrpc»: «2.0», «method»: «sum», «params»: [1,2,4], «id»: «1»}
и
get: host.ru/sum/1.json + {«params»:[1,2,4]}
И если вы изначально пишите RESTfull приложение вопрос об изобретении API над рабочим приложением отпадает сам собой. Тестировать вам приходится только свое приложение и писать изменения только в приложение. И курить левую документацию к левой софтине нет никакой необходимости.
Вы же предлагаете следующий сценарий:
1. Подключить API
2. обложить тестами API
Когда требуются изменения:
3. Писать тесты для app
4. Писать код в app (или наоборот)
5. Писать тесты для API
6. Писать код в API (или наоборот)
Когда в классической схеме RESTfull
1. пишем тест
2. пишем код
(или наоборот)
host.ru/api + {«jsonrpc»: «2.0», «method»: «sum», «params»: [1,2,4], «id»: «1»}
и
get: host.ru/sum/1.json + {«params»:[1,2,4]}
И если вы изначально пишите RESTfull приложение вопрос об изобретении API над рабочим приложением отпадает сам собой. Тестировать вам приходится только свое приложение и писать изменения только в приложение. И курить левую документацию к левой софтине нет никакой необходимости.
Вы же предлагаете следующий сценарий:
1. Подключить API
2. обложить тестами API
Когда требуются изменения:
3. Писать тесты для app
4. Писать код в app (или наоборот)
5. Писать тесты для API
6. Писать код в API (или наоборот)
Когда в классической схеме RESTfull
1. пишем тест
2. пишем код
(или наоборот)
0
Касательно тестов — для конечного клиента писать не нужно, тут имелось в виду тесты к базовой реализации клиента. Код конечного клиента генерируется на основе smd-файла.
В чем отличие от REST: наличие какого-то стандартизированного механизма auto-discovery.
Предположим, что у нас есть уже веб-сервис и сгенерированный клиент на основе smd-схемы.
В веб-сервисе появились новые методы. В случае REST — нужно вручную написать к ним реализацию в клиенте.
В случае с auto-discovery — нужно всего-лишь сгенерировать нового клиента — профит.
Курить левую документацию не нужно, т.к. это JSON-RPC :)
В чем отличие от REST: наличие какого-то стандартизированного механизма auto-discovery.
Предположим, что у нас есть уже веб-сервис и сгенерированный клиент на основе smd-схемы.
В веб-сервисе появились новые методы. В случае REST — нужно вручную написать к ним реализацию в клиенте.
В случае с auto-discovery — нужно всего-лишь сгенерировать нового клиента — профит.
Курить левую документацию не нужно, т.к. это JSON-RPC :)
0
Немного дополню, если в проекте используется сваггер, и проект построен по REST, то слой API и DTO модели можно также сгенерить github.com/swagger-api/swagger-codegen
Чет поздно на дату статьи посмотрел :)
Чет поздно на дату статьи посмотрел :)
0
В своем проекте (трекер, ссылка в профиле), использую Zend_Json_Server, но сам протокол немного модифицировал.
Дело в том, что мне понравился вариант не только указания метода, который должен вызваться на сервере, но и наоборот, указание метода, который должен вызваться на клиенте.
Вообщем, лучше объясню наглядно. Стандарт json-rpc подразумевает такие запросы-ответы:
Я же сделал так:
Поясню что тут происходит:
вызов такой (у меня плагин для jquery):
Здесь
method — «Class.Method». На сервере происходят свои обрабоки, для того, чтобы вызывать только те методы классов, которые можно.
params — ну тут понятно.
callback — callback-функция, о ней ниже
options — опции, характерные для $.ajax
1. При ответе должны вызваться методы
2. При ответе вызывается метод
3. При ответе вызывается
Лично мне — очень удобно!
Думал написать статью, чтобы расписать все подробно, но времени нету. Так что сжато написал в комментарии :)
Дело в том, что мне понравился вариант не только указания метода, который должен вызваться на сервере, но и наоборот, указание метода, который должен вызваться на клиенте.
Вообщем, лучше объясню наглядно. Стандарт json-rpc подразумевает такие запросы-ответы:
тут я ваш пример скопипастил
--> {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"jsonrpc": "2.0", "result": 19, "id": 3}
--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}
--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "foobar", "id": "2"}
]
<-- [
{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": "2"}
]
Я же сделал так:
1.
--> {"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}
<-- {"result":[{"method":"object.method","params":555},{"method":"object2.method5","params":[1,2,3,4]}],"id":"1","jsonrpc":"2.0"}
2.
--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": [{"method":"object.method","params":555}, {"aaa":18}], "id": 1}
3.
--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}
Поясню что тут происходит:
вызов такой (у меня плагин для jquery):
$.jsonrpc(method, params, callback, options);
Здесь
method — «Class.Method». На сервере происходят свои обрабоки, для того, чтобы вызывать только те методы классов, которые можно.
params — ну тут понятно.
callback — callback-функция, о ней ниже
options — опции, характерные для $.ajax
1. При ответе должны вызваться методы
object.method(555)
и object2.method([1,2,3,4])
2. При ответе вызывается метод
object.method(555)
и callback функция callback({"aaa".18})
3. При ответе вызывается
callback(18);
Лично мне — очень удобно!
Думал написать статью, чтобы расписать все подробно, но времени нету. Так что сжато написал в комментарии :)
0
Мысль понятна, но вам не кажется, что сервер не должен знать. что происходит на клиенте в общем случае? :)
+2
Мы с моим коллегой по предыдущему проекту очень много спорили об этом. Он, кстати, написал свою реализацию (довольно крутую) json-rpc для друпала. Он тоже скептически отнесся к моей реализации :)
Но, удобство, реально очевидное.
Например, чат.
Пользователь посылает текст в чат. И получает ответ, в котором перечислены следующие методы:
1. сообщение добавлено
2. Надо вывести 2 новых собщения в чат
3. Онлайн изменился
4. что-нибудь ещё.
Т.е. фронтенд-программист просто пишет эти методы. А бекенд — их вызывает. Круто :)
В целом, в моем плагине есть возможность им пользоваться в обычном асинхронном режиме — один запрос, один ответ в колбек. Но, я, использую только эту свою реализацию, уж ооочень мне удобно с ней работать.
Но, удобство, реально очевидное.
Например, чат.
Пользователь посылает текст в чат. И получает ответ, в котором перечислены следующие методы:
1. сообщение добавлено
2. Надо вывести 2 новых собщения в чат
3. Онлайн изменился
4. что-нибудь ещё.
Т.е. фронтенд-программист просто пишет эти методы. А бекенд — их вызывает. Круто :)
В целом, в моем плагине есть возможность им пользоваться в обычном асинхронном режиме — один запрос, один ответ в колбек. Но, я, использую только эту свою реализацию, уж ооочень мне удобно с ней работать.
0
Изящно.
* auto-discovery — захватывает все public методы класса? куда девать public методы не используемые в API?
* mass-assignment?
* auto-discovery — захватывает все public методы класса? куда девать public методы не используемые в API?
* mass-assignment?
0
habrahabr.ru/post/150803/#comment_5108827
(не туда запостил)
(не туда запостил)
0
>* auto-discovery — захватывает все public методы класса? куда девать public методы не используемые в API?
Вообще не делать их public) ну или добавить в $hiddenMethods, благо protected.
>* mass-assignment?
Тут не применимо, сигнатуры методов известны:)
Вообще не делать их public) ну или добавить в $hiddenMethods, благо protected.
>* mass-assignment?
Тут не применимо, сигнатуры методов известны:)
0
А насколько возможно и без костылей за один такой JSON-RPC запрос в этой реализации передать несколько методов разных классов со своими параметрами и от всех их получить единый ответ?
0
Сделать общий proxy-класс, в котором описать все эти методы и сделать из него RPC Server.
Казалось бы, костыль. Но! Предположим, что мы делаем апи для мобильного приложения. Набор методов уже заранее известен, они находятся в разных классах. Создаем MobileAppServer (отнаследованный от BaseJsonRpcServer), в котором собираем все методы воедино — ничего лишнего. В такой реализации доступна пост-обработка результатов этих методов, например сокрытие лишних переменных в результирующих объектах. Как-то так.
Казалось бы, костыль. Но! Предположим, что мы делаем апи для мобильного приложения. Набор методов уже заранее известен, они находятся в разных классах. Создаем MobileAppServer (отнаследованный от BaseJsonRpcServer), в котором собираем все методы воедино — ничего лишнего. В такой реализации доступна пост-обработка результатов этих методов, например сокрытие лишних переменных в результирующих объектах. Как-то так.
0
В Зенде проблема еще, что для SMD не вытаскивает комментарий/описание метода, а это зачастую важно. Также неясно поведение, когда серверные методы реализуются множеством классов — если там есть одинаковые методы, будет использован только последний. Нет возможности использовать что-то типа неймспейсов (на базе имен классов) или переопределять название метода. В результате пришлось писать свою костыльную реализацию :)
0
Спасибо за статью!
Я тоже одно время присматривался к этому способу создания API (делал на Python/Django и php) для обмена данными на смену SOAP. Но основной вопрос возник — как сделать кроссплатформенную авторизацию, чтобы сервер был допустим на Django, а клиент на php?
В простейшем случае конечно можно сделать авторизацию через веб-сервер и передавать логин и пароль через url, но хотелось бы что-то более серьезное.
Подскажите идеи.
Я тоже одно время присматривался к этому способу создания API (делал на Python/Django и php) для обмена данными на смену SOAP. Но основной вопрос возник — как сделать кроссплатформенную авторизацию, чтобы сервер был допустим на Django, а клиент на php?
В простейшем случае конечно можно сделать авторизацию через веб-сервер и передавать логин и пароль через url, но хотелось бы что-то более серьезное.
Подскажите идеи.
0
Использовать HTTP Basic Auth. В клиенте достаточно добавить логин и пароль в массив $CurlOptions :)
Использовать токены через HTTP-заголовки. Для получения токенов можно написать необходимый метод.
Использовать токены как параметры метода.
помимо этих идей или их раскрыть надо?
0
Спасибо.
Да, похожие идеи были, но из этого списка только первый вариант относительно стандартным можно считать.
Для 2 и 3 придется существенно допиливать библиотеки и если для себя это нормально, то для организации обмена данными с чужими системами уже создает неудобство — им тоже придется допиливать свои библиотеки.
Да, похожие идеи были, но из этого списка только первый вариант относительно стандартным можно считать.
Для 2 и 3 придется существенно допиливать библиотеки и если для себя это нормально, то для организации обмена данными с чужими системами уже создает неудобство — им тоже придется допиливать свои библиотеки.
0
Добавьте, пожалуйста, свой класс в Composer. В этом нет ничего сложного.
И конечно же хотелось бы привести форматирование к общепринятым стандартам.
И конечно же хотелось бы привести форматирование к общепринятым стандартам.
0
если делать запрос через метод call (не магический __call, а обычный), то запросу не назначается id. Из-за этого processCall($call) возвращает null.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
JSON-RPC 2.0 и PHP