Как это вообще должно работать: пользователь заходит на сайт, и видит окошко, куда можно разговаривать. После того как пользователь послал сообщение, оно прилетает на указанный джаббер аккаунт. Получатель этого сообщения может написать ответ и оно придёт посетителю сайта.
Что для этого нужно:
- Jabber сервер, можно публичный, можно локальный. Я выбрал Openfire и установил его локально. Сервер должен поддерживать Bosh - XEP-0124: Bidirectional-streams Over Synchronous HTTP, об этом чуть позже.
- JS библиотека, которая будет реализовывать джаббер-клиент на сайте. Я взял Strophe. Это достаточно низкоуровневая библиотека, в которой нет функций типа "ПослатьСообщение(Куда, Текст)". Для достижения нужных действий нужно вручную составлять команды джаббер серверу (в XML). Удобные средства для создания XML в Strophe есть :)
BOSH
JS не умеет создавать TCP соединения с другим сервером/клиентом, что необходимо для реализации джаббер-клиента. JS может посылать только HTTP запросы. Поэтому нужен специальный механизм, который позволит работать с TCP соединениями посредством HTTP. Это и есть BOSH.По-умолчанию BOSH в Openfire включён и имеет адрес
http://localhost:7070/http-bind
. Но если указать этот адрес при соединении, ничего не выходит. Проблема хорошо описана здесь, что бы заработало нужно написать редирект для апача и раскомментировать модули proxy_module и proxy_http_module:httpd.conf:
ProxyRequests Off
ProxyPass /http-bind http://127.0.0.1:7070/http-bind/
ProxyPassReverse /http-bind http://127.0.0.1:7070/http-bind/
Чат на сайте
Итак, всё очень просто, устанавливаем Openfire, создаём пользователя, например, site, и создаём тестовую страницу (в качестве основы я брал строфовский пример echobot). На странице есть поле, куда пользователь пишет своё сообщение, и поле с историей чата.Пишем обработчик загрузки страницы, который будет логинится на джаббер сервер:
$(function () {
connection = new Strophe.Connection('/http-bind');
connection.connect('site@r1c', 'site', onConnect);
});
В обработчике onConnect мы добавляем "слушателя" на события, связанные с приходом сообщений (в случае успешного логина): function onConnect(status){
if (status == Strophe.Status.CONNECTING) {
log('Strophe is connecting.');
}
else if (status == Strophe.Status.CONNFAIL) {
log('Strophe failed to connect.');
}
else if (status == Strophe.Status.DISCONNECTING) {
log('Strophe is disconnecting.');
}
else if (status == Strophe.Status.DISCONNECTED) {
log('Strophe is disconnected.');
}
else if (status == Strophe.Status.CONNECTED) {
log('Strophe is connected, ' + connection.jid);
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.send($pres().tree());
}
}
Обработчику onMessage приходят XML данные. Разбираем их что бы узнать текст сообщения, кто отправитель и т.д.:function onMessage(msg) {
var to = msg.getAttribute('to');
var from = msg.getAttribute('from');
var type = msg.getAttribute('type');
var elems = msg.getElementsByTagName('body');
if (type == "chat" && elems.length > 0) {
var body = elems[0];
AddText(Strophe.getText(body), 'in');
}
// we must return true to keep the handler alive.
// returning false would remove it after it finishes.
return true;
}
Обработчик кнопки "Отправить" формирует XML с необходимыми данными и просит Strophe отправить их. В качестве принимающего используется пользователь admin:function Send(message) {
var msg = $msg({to: 'admin@r1c', from: connection.jid, type: 'chat'}).c('body').t(document.URL + '\n' + message);
connection.send(msg.tree());
AddText(message, 'out');
$('input#message').val('');
}
Итог

В итоге получился очень простой набросок, позволяющий общаться по джабберу через веб-страницу. Мне было интересно узнать как это работает в принципе, поэтому я не стал копать дальше. Что-то мне подсказывает там есть куча подводных камней :)
Можно придумать ещё очень много усовершенствований. Например:
- Нормальный интерфейс чата на сайте :)
- Автоматическая регистрация новых пользователей на джаббер-сервере, если в этом есть необходимость. Для этого можно использовать In-band registration - регистрация через XML команды джаббера, а не через веб-интерфейс.
- Сохранение состояния чата при переходе между разными страницами сайта
- Сохранение истории чата на сервере
- и т.д.
а так ты чем сейчас занимаешься? неужели питон питоныч тебя поглотил?
ОтветитьУдалитьПитон это будущее, надеюсь :)
ОтветитьУдалитьНда, этот блоггер та ещё деревяшка :(