A gateway between Jabber clients that talk HTTP and Jabber servers that talk XMPP. This is a Jabber standard called XEP-0124
Because I work behind a firewall and am restricted in what I can install on my PC.
This uses HTTP to connect to a Jabber server - so it is firewall friendly - and
at least one client (JWChat) is implement using AJAX and so does not require a local
Oh and my hosting plan gives me access to a Ruby web server but not a Java web server.
- Implements optional SSL signon (non-SASL) to the Jabber server.
- Correctly implements polling behavior
There is really only one file here that implements XEP-0124 - xmpphttpbind.rb.
You could put this anywhere you like on Ruby's load path and it will work.
I use Rails so I put it in my application's lib directory.
I kept the code independent of any particular web framework, so you will need to write a
short handler for HTTP requests that is responsible for forwarding the requests to the
module and taking responses back from it. Here is the one I use for Rails:
As you can see. Its pretty short.
class RhbController < ApplicationController
# Handles HTTP Bind requests
xmpp_response = XMPP::HTTPBind::parse request.raw_post
logger.debug 'Response: ' + xmpp_response
render :xml => xmpp_response
rescue XMPP::HTTPBind::RHBNotFoundException => bre
render_text '', '404 - Not Found'
rescue XMPP::HTTPBind::RHBForbiddenException => bre
render_text '', '403 - Forbidden'
rescue Exception => e
logger.debug e.inspect + "\n" + e.backtrace.join("\n")
render_text '', '400 - Bad Request'
This version correctly implements polling behaviour. If you want to force the client to poll
you should set REQUESTS to 0 in xmpphttpbind.rb.
xmpphttpbind uses the xmpp4r gem which is available on rubyforge. This is the command I used
to install it:
Because of the way that XEP-0124 works you will have to make sure that your Ruby web server
can handle more than one simultaneous connection. I use Apache+FastCGI+Rails on my production
server and Apache+SCGI+Rails on my development server. I got bit by this on my
development server. I had to edit
gem install xmpp4r http://rubyforge.org/frs/download.php/14264/xmpp4r-0.3.gem
config/scgi.yaml to include a
:maxconns: line, specifically:
The HTTP Jabber client I use is JWChat. You should install
this on the same web site as
xmpphttpbind. I put it in
public/jwchat. If you're using
Apache+Rails remember to edit your
.htaccess file to serve jwchat up directly rather then send
requests for http://yoursite/jwchat to Rails. You also need to edit the
to tell it where the client should send its HTTP requests - i.e. to the controller above.
There is an example config.js file in subversion too.
This is currently only tested with Rails+Apache+FastCGI/SCGI and JWChat. It may or may
not work with any other combination - there are some things that I have not implemented
yet and then there are always bound to be bugs too. However I would like to get this
working across the board so let me know how it goes if you try and use it.
FastCGI works by running several process that handle HTTP requests. This is a problem
if you want to hold open a persistent connection to another server and have HTTP requests
route through that connection - the socket will be in one process and all of the other
processes will need to make sure they use that one socket. Enter DRb (Distributed Ruby).
xmpphttpbind runs a DRb server in one of the FastCGI process on a first-come, first-served
basis: all requests look to see if the DRb server exists first and if so they connect to it,
otherwise they create one. Race conditions between processes are avoided by grabbing a file
lock for the duration of the lookup. This has another beneficial side-effect: If the
specific process that created the DRb server dies, another one will be created just as
soon as it is needed (and not before).