XML-RPC, CodeIgniter, LiveJournal и куча проблем :)

Недавно ко мне обратился читатель с просьбой помочь отправить сообщение в LiveJournal через XML-RPC протокол. При этом использовать нужно было библиотеку фреймворка CodeIgniter.
Честно говоря, когда я вижу такие вопросы, то сразу пробую найти готовое решение. Этот случай исключением не был и подходящая инструкция быстро нашлась. XML-RPC и кросспостинг в ЖЖ. Константин Лихачев в ней подробно рассказывает об отправке сообщений, единственное но – используется Incutio XML-RPC Library, а не встроенная библиотека CI.
Раз работает код с использованием Incutio XML-RPC, то сервис 100% рабочий и нужно просто правильно передать параметры в библиотеке CodeIgniter'а.
Думаю: «Почему бы не помочь человеку? Опыт работы с CI у меня есть, с документацией JiveJournal разбираться не нужно, т.к. список всех нужных параметров есть в статье Константина. Минут за 20 сделаю…»
Мне пора бы привыкнуть, что когда я так думаю, эти 20 минут часто превращаются в 2-3 часа. ![]()
Проблема была такая. Встроенная библиотека CodeIgniter требует, чтобы все параметры запроса были заданы в виде массива. При этом если нужно передавать структуры данных, получается куча вложенных друг в друга массивов.
И пропустить один из них (что я и сделал) или вставить лишний очень легко.
По-идее, именно для таких ситуаций предусмотрен режим отладки. Но в этом режиме библиотека CI выводит только XML ответ сервера, а мне нужно было посмотреть на XML строку, которая отправляется в запросе.
Примечание. Ответ сервера:
-
Can't use string ("Array") as a HASH ref while "strict refs" in use at /home/lj/cgi-bin/Apache/LiveJournal.pm line 1779.
лично мне ни о чем не говорит (на perl я не программирую). Кстати, тот же WordPress в таких случаях возвращает «parse error. not well formed» – на мой взгляд, более понятный ответ, хоть и не очень информативный.
В документации LiveJournal есть примеры XML запросов, которые нужно отправить для добавления записи, т.е. достаточно просто сравнить их со своими и все проблемы будут видны.
После нескольких неудачных попыток узнать что все-таки отправляется серверу, пришлось лезть в исходники библиотеки.
Чтобы вывести запрос я добавил строку
-
echo '<pre>'.htmlspecialchars($op).'</pre>';
в методе sendPayload перед
-
if ( ! fputs($fp, $op, strlen($op)))
Не очень элегантное решение, но зато сразу стало ясно, в чем проблема.
Привожу рабочий код отправки сообщения в livejournal.
-
class LiveJournal extends Controller {
-
-
private $LJ_url = 'http://www.livejournal.com/interface/xmlrpc';
-
private $LJ_login = 'your login';
-
private $LJ_pass = 'your pass';
-
-
function LiveJournal()
-
{
-
parent::Controller();
-
-
//подключаем XML-RPC библиотеку
-
$this->load->library('xmlrpc');
-
}
-
-
function index()
-
{
-
$this->xmlrpc->server($this->LJ_url);
-
-
//отправляем challange-запрос
-
$this->xmlrpc->method('LJ.XMLRPC.getchallenge');
-
-
if (!$this->xmlrpc->send_request()) {
-
echo $this->xmlrpc->display_error();
-
}
-
else {
-
//если получен ответ с challenge-строкой, читаем его и отправляем запись
-
$challenge_response = $this->xmlrpc->display_response();
-
-
//формируем массив с данными для создания записи
-
$request = array(
-
array(
-
array(
-
'username'=>array($this->LJ_login,'string')
-
,'auth_method'=>array('challenge','string')
-
,'auth_challenge'=>array($challenge_response['challenge'],'string')
-
,'auth_response'=>array(md5($challenge_response['challenge'].md5($this->LJ_pass)),'string')
-
,'ver'=>array('1','string')
-
,'event'=>array('Заголовок записи','string')
-
,'subject'=>array('Текст записи …','string')
-
,'year'=>array(2009,'int')
-
,'mon'=>array(11,'int')
-
,'day'=>array(12,'int')
-
,'hour'=>array(5,'int')
-
,'min'=>array(27,'int')
-
,'props'=>array(
-
array(
-
'opt_backdated'=>array(true,'boolean')
-
,'taglist'=>array('tag 1, tag 2, tag 3','string')
-
)
-
,'struct')
-
,'security'=>array('public','string')
-
)
-
,'struct'
-
)
-
);
-
-
//отправляем запрос серверу
-
$this->xmlrpc->method('LJ.XMLRPC.postevent');
-
$this->xmlrpc->request($request);
-
if (!$this->xmlrpc->send_request()) {
-
echo $this->xmlrpc->display_error();
-
}
-
else {
-
$postData = $this->xmlrpc->display_response();
-
//$postData['url'] – содержит адрес созданной записи
-
}
-
}
-
}
-
}
Несколько пояснений. Публикация сообщения выполняется в 2 этапа.
1) Нужно получить challenge строку, которая хешируется (строка 36) вместе с вашим паролем и используется вместо него. Это сделано для того, чтобы не передавать пароль в открытом виде.
2) Отправка самого сообщения. Как раз тут и нужно формировать структуру с данными. Как видите, мы везде используем массивы с двумя элементами. Первый элемент содержит передаваемое значение, второй – тип этого значения. Если нужно передать структуру, то первый элемент должен быть массивом.
Выглядит такая конструкция громоздкой и заполнять ее нужно внимательно, особенно если вы привыкли к библиотеке вроде Incutio XML-RPC. Кстати, эту библиотеку не сложно подключить и использовать вместо стандартной CodeIgniter’а.
Вообще в последнее время складывается впечатление, что разработчики забросили фреймворк. Хотя, возможно, я не прав, а Ellislab просто все силы тратит на свою CMS, вторую версию ExpressionEngine, которая вроде бы будет работать на основе CodeIgniter.
Очень не хочется, чтобы они забросили CI.
Постовой
Что выгоднее, услуги приходящего бухгалтера или ведение бухгалтерии у профессионалов? Ответ здесь
Понравилась статья? Подписывайтесь на продолжение
!
Опубликовано в CodeIgniter, PHP, Web разработка Комментарии (20) »
Комментарии (20)
Вы можете отслеживать обсуждение записи с помощью RSS 2.0 ![]()
Вы также можете оставить комментарий, или трекбек с Вашего сайта.









CI не заброшен, просто его разрабатываю с учетом нужд самой компании. Это и есть огромнейший минус, но плюсов на мой взгляд много больше. Хотя поддержка php 4 версии, имхо, бред, слишком много ограничений.
Такой минус есть у многих open source продуктов. С другой стороны раз в нужды компании входит разработка CMS (ExpressionEngine), то и CI будет скорее всего развиваться в правильном направлении
По поводу "не забросили CI" – я тут посмотрел в сторону Yii и должен сказать, что Yii намного "вкуснее". Да, порог вхождения вышем чем у CI, но оно того стоит.
Я тоже понемногу пробую работать с Yii, выглядит все очень интересно. Порог вхождения может быть и выше, но скорее всего только в том случае если человек не занимался ООП.
В любом случае Yii у меня на первом месте в качестве альтернативы CI
Yii – зачем изучать еще один фреймворк?
Мне кажется лучше начать учить еще один язык или совершенствовать основы, а с задачами php и codeigniter справится, слегка подпиленный.
В замен codeigniter я выбрал python + django.
Дело в том, что с новым фреймворком разобраться проще и быстрее, чем с новым языком
Учить Yii – громко сказано. При средних знаниях PHP и ООП через 3-4 дня можно уже нормально работать.
Я python – другое дело. Сам язык, библиотеки, может быть какие-нибудь особенности в настройке сервера, все это требует времени. Занятие, конечно, очень перспективное… язык перспективный.
Кстати, я хотел спросить. Есть сейчас заказы на разработку на питоне (для фрилансеров)?
Не так много как бы хотелось. Но, питон можно использовать и при работе с пыхой, решать серверные задачи +) Здесь скорее можно рассчитывать на парочку постоянных заказчиков.
Если говорить о потоке заказов, то тут лучше всего подходит zend и drupal, вот уж где очень много проектов и оплата соответствующая.
А по части настройки сервера и вообще, все очень просто +) По крайне мере в linux, поставить питон и написать первый скрипт, заняло порядка 5 минут +)
А пхп все равно устает, ну представь, на скольких C подобнымх языках ты писал? Один и тот же синтаксис, просто морально устаешь.
Это понятно, что "hello,world" можно за 5 минут запустить. Я имел ввиду, например, какие-то нюансы в настройке, которые могут проявиться при высокой нагрузке или что-нибудь подобное… не знаю точно, может быть действительно все просто и очевидно.
Устать, ИМХО можно от любого синтаксиса. Просто пока учишь новый язык, есть энтузиазм, а потом, когда пишешь примерно один и тот же код в 10 раз – энтузиазма нет
Владимир, огромное спасибо, что помогли )
Как я только не мучался с этим исходным массивом для отправки.
Теперь все понятно =)
Теперь буду экспериментировать дальше с xml-rpc и ЖЖ.
Владимир, не сочтите за дерзость, но у меня есть маленькие заметки-наблюдения =):
1. event – текст самой записи, а subject – тема. но это мелочь.
2. ЖЖ отлично "кушает" формат 'ver'=>array(2,'int') вместо 'ver'=>array('1','string');
3. самое интересное:
3.1 CI 1.7.2 на локальной машине под Денвером получает в ответ от сервера LJ ошибку "Application failed during request deserialization: unclosed token at line 107, column 0, byte 1490 at /usr/lib/perl5/XML/Parser.pm line 187" если хоть что-то из "event", "subject" или "taglist" написано по-русски!. Может только у меня.
3.2. как только выложил на хостинг под CI 1.7.1 с русскими словами ошибки не возникло никаких проблем.
до этого я пытался исключительно на локальной машине это запустить и ошибка из п.3.1 у меня уже была. поэтому, я немного удивился когда даже Ваш код у меня не отработал сразу. На локальной машине под Денвером все отправляется отлично, если написано по-английски. (UTF-8 использую всегда и повсюдю, так что не в кодировке дело). Идентичный код, но на сервере, отработал на "ура".
спасибо Вам огромное еще раз =)
1) Согласен, я ошибся. С ЖЖ не работал (и в общем-то не планирую), поэтому внимания не обратил
2) К сожалению это один из сложных моментов в работе с XML-RPC. Тут все зависит от разработчиков сервера. Можно написать код так, что он будет принимать оба типа параметров и правильно их обрабатывать, а можно так, что ошибка будет возникать если тип не соответствует указанному. В любом случае лучше всегда ориентироваться на документацию. Если там сказано int, то и отправлять нужно int. (Я сам типы параметров ЖЖ не проверял, ориентировался на статью Константина).
3) я тестировал именно с версией 1.7.2. Использовал WAMPSERVER на локальной машине. Посоветовать могу только сравнить конфиги PHP и Apache, ну и еще раз проверить кодировку (все-таки когда речь идет о русских буквах, то на 99,9% проблема с кодировкой, кстати, можно посмотреть в php.ini параметр default_charset).
пожалуй вы правы. по умолчанию у меня в php.ini (который от Денвера) default_charset вообще закоментирован. Так что, наверно, либо в php.ihi, либо в .htaccess, либо напрямую прописывать
header('Content-Type: text/html; charset=utf8');и будет счастье.самое обидное, что я как оказалось много раз верно формировал массив, но получал эту глупую ошибку о том, что LJ не может рассериализовать данные. А ошибка была с кодировкой. Печально.
Владимир, уж простите, что достаю, но просто хотел кое что отметить. Опция opt_backdated, если установлена в true, еще и запрещает показ сообщения во френдлентах друзей. Так что пусть если что никто не удивляется – почему пост есть, а френды его не видят через ленту.
=)
Я никогда не считаю комментарии попыткой меня достать
А чем больше полезной информации вы приведете, тем лучше, ценность этой статьи только повысится. Может кому-то поможет.
Сам я разбираться с LJ не буду (во всяком случае не планирую).
Стоит посмотреть в сторону Recess фреймворка, молодой и без болезней присущих CI
Спасибо за совет. Я посмотрел парочку их скринкастов, выглядит действительно очень неплохо.
Recess
Подскажите элементарный CMS для фотогалереи без базы данных
чтоб можнонужно было просто залить изображения в папку по FTP
и они автоматически добавились в галерею, желательно с простой админкой
разрешающей массово редактировать фотки, прописать к ним описание
и управлять коментариями, возможно так-же и функция оценки изображений.
В итоге должно получится что-то вроде того что есть на фотогалерееhttp://dyon.ru/
Только там отсутствует админка.
К сожалению, я с такими не работал. Поэтому подсказать не могу.
Скажите, а кто нибудь потом побывал редактировать добавленный пост через веб-интерфейс ЖЖ?
У меня выдаёт ошибку на странице редактирования:
—–
Client error: Invalid text encoding: Cannot display this post. Please see http://www.livejournal.com/support/encodings.bml for more information.
—–
При этом пост нормально отображается на других страницах и ни каких проблем с кодировками нету.
Правда скрипт делал я на Python и использовал для отправки стандартный модуль xmlrpclib, но мне кажется что дело не в этом. Все тексты передавал в кодировке UTF-8.
Всё, спасибо, разобрался сам. Я не указал в запросе параметр 'ver'. Задал его значение в 1 и всё стало нормально.
http://livejournal.com/doc/server/ljp.csp.versions.html