How to properly connect strophe.js client with Prosody server using XMPP protocol

4.4k views Asked by At

I've installed and configured Prosody server. It listens on standard localhost:5222. Added admin in configuration file - [email protected]. Every request to server ended up with error:

<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" id="" version="1.0">
    <stream:error>
        <not-well-formed xmlns="urn:ietf:params:xml:ns:xmpp-streams"/>
    </stream:error>
</stream:stream>

As a client I would like to use strophe.js. I'm sending only presence stanza ($pres). Here is my code.

'use strict';

angular.module('xmppTestApp')
    .controller('ChatCtrl', function () {

    var vm = this;

    var url = "http://localhost:5222";
    var connection = null; 

    var output = document.getElementById("output");

    function log(message) {
        var line = document.createElement("div");
        line.textContent = message;
        output.appendChild(line);
    }

    function connectHandler(cond) {
        if (cond == Strophe.Status.CONNECTED) {
            log("connected");
            connection.send($pres());
        }
        else {
            log("not connected");
        }
    }

    vm.connectB = function() {
        var username = document.getElementById("username").value;
        var password = document.getElementById("password").value;

        console.info(url);
        console.info(username);
        console.info(password);

        connection = new Strophe.Connection(url);
        connection.connect(username, password, connectHandler);
    }
});

In console i see error:

XMLHttpRequest cannot load http://localhost:5222/. No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:9000' is therefore not allowed access.

How can I add Access-Control-Allow-Origin' header to my request?

When I'm trying send request to localhost:5222 (without http) I'm getting:

XMLHttpRequest cannot load localhost:5222. Cross origin requests are only supported for HTTP.

And when I send it through websocket, I'm getting:

WebSocket connection to 'ws://localhost:5222/' failed: Error during WebSocket handshake: Unexpected response code: 200 

Fiddler provides me protocol violation report:

The server didn't return properly-formatted HTTP Headers. Maybe missing altogether 
(e.g. HTTP/0.9), maybe only \r\r instead of \r\n\r\n?
1

There are 1 answers

9
fpsColton On BEST ANSWER

First and foremost, it looks like you're trying to connect directly to port 5222 (typically used for XMPP), but in order to use Strophe from a client-side webpage, you must use HTTP-Binding (aka BOSH).

XMPP vs BOSH

Strophe speaks XMPP, but it is unique in that it does not actually transmit data using the XMPP protocol, instead it relies on BOSH for this (that is, Bidirectional-streams Over Synchronous HTTP). This is because the XMPP protocol is designed to keep the client and server connected at all times, and we all know this isn't how HTTP works. To put it in simple terms, BOSH allows your HTTP client to asynchronously receive data without having to explicitly make a request for it. If you have more questions regarding BOSH let me know and I'll try my best to explain what is does and why you need it.

You must enable this feature in prosody before connecting with Strophe, check out this link to get setup.

Prosody Docs - Setting up BOSH

Once you've setup BOSH, you will need to change your client side code to use a different address. It is likely that you have setup the path+port for BOSH to something such as :5280/http-bind/. At this point you need to make sure that Strophe is using this URL instead of the actual XMPP port of 5222.

Finally, CORS is required for any resource outside of your websites domain and port. In your example, your client has to make a request to a URL which is running on a different port+domain as the page itself (the connection between Strophe and Prosody). Good news is, Prosody already supports CORS and enabling it is very straightforward. All of this is explained in much further detail on the page I linked earlier.

Hope that helps!