3

I've installed and configured Prosody server. It listens on standard localhost:5222. Added admin in configuration file - user1@example.com. 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?
Mickaël Rémond
  • 9,035
  • 1
  • 24
  • 44
magos
  • 3,371
  • 4
  • 29
  • 54

1 Answers1

6

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!

fpsColton
  • 873
  • 5
  • 11
  • Thank you for your answer. I've configured BOSH and it works, but I'm still getting error about CORS, despite I've added to configuration file: cross_domain_bosh = true Error: XMLHttpRequest cannot load http://localhost:5280/http-bind. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. What's more - I would be grateful if you'd give me some advice how to register users. From Prosody's documentation I know I need to set allow_registration = true But how then establish specific login and password? – magos Dec 16 '14 at 22:32
  • I would try restarting prosody after making the changes to the config, you can easily test to see if CORS is enabled by browsing to `localhost:5280/crossdomain.xml`. If you cannot find this file, then CORS is not yet enabled. Also, make sure that `cross-domain-bosh = true` is in the global section of your config. Also, try adding one more backslash after `/http-bind`, ex: `/http-bind/`. – fpsColton Dec 16 '14 at 22:43
  • It seems the problem is with crossdomain.xml. What should I add to it? Or is there any way to generate it? – magos Dec 16 '14 at 22:49
  • Regarding user registration, once you have configured your server to allow registration, the rest is up to your client side code to make it happen. The process for registering a user is outlined in XEP-077 (http://xmpp.org/extensions/xep-0077.html). Once you get going with Strophe, the XEP documents will become an invaluable resource to you. The process of user reg is too much to explain in a comment, it is worthy of it's own question (if it hasn't already been asked!). – fpsColton Dec 16 '14 at 22:49
  • The `crossdomain.xml` should be generated for you by Prosody. I've never used Prosody personally, so I'm not sure why it isn't working. Have you tried restarting all related Prosody services? – fpsColton Dec 16 '14 at 22:51
  • It may be possible that Prosody is unable to create the CORS file due to permissions, if you can, try running it as an Administrator. Also make sure the entry in the config isn't under `VirtualHost` or `Component`. – fpsColton Dec 16 '14 at 22:53
  • Yes, I've restarted even machine and run Prosody as administrator. Entry is in global scope and over VirtualHost and Component. I'm still trying to find a mistake. Too bad it isn't mentioned in documentation... – magos Dec 16 '14 at 23:15
  • I would try using your system IP instead of `localhost`, especially after reading https://code.google.com/p/chromium/issues/detail?id=67743 – fpsColton Dec 16 '14 at 23:27
  • Prosody pre 0.10 had a bug where a cross domain issue would be sent back due to incomplete headers in some error conditions. So basically you may think you have a cross domain issue but you have some other error and the prosody server bailed early, tried to send you the error, but didn't send complete headers and therefore you get the CORS error. 0.10+ solves this – Tony Mar 15 '17 at 22:49