如果 JS 代码未托管在服务器上(CORS?),Strophejs XMPP Hello World 无法连接到服务器

Posted

技术标签:

【中文标题】如果 JS 代码未托管在服务器上(CORS?),Strophejs XMPP Hello World 无法连接到服务器【英文标题】:Strophejs XMPP Hello World cant connect to server if JS code not hosted on server (CORS?) 【发布时间】:2014-10-29 15:46:20 【问题描述】:

我正在尝试 Jack Moffit 书中的一个示例:Professional XMPP Programming with javascript and jQuery。具体来说,我正在尝试第 3 章中的 hello world 应用程序,它应该使用 bosh 通过 Web 界面登录到 xmpp 服务器。我已经从http://media.wiley.com/product_ancillary/10/04705407/DOWNLOAD/9780470540718_Professional%20XMPP_Code%20Download.zip下载了所有必要的代码。

当我在 Chrome 中打开文件 Hello.html 并打开 JavaScript 控制台时,没有任何问题,因此文件中引用的脚本和 css 文件似乎已成功加载。

这是 Hello.html 文件:

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
              "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <title>Hello - Chapter 3</title>

        <link rel='stylesheet' href='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/cupertino/jquery-ui.css'>
        <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js'></script>
        <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js'></script>
        <script src='../scripts/strophe.js'></script>
        <script src='../scripts/flXHR.js'></script>
        <script src='../scripts/strophe.flxhr.js'></script>

        <link rel='stylesheet' href='hello.css'>
        <script src='hello.js'></script>
      </head>
      <body>
        <h1>Hello</h1>

        <div id='log'>
        </div>

        <!-- login dialog -->
        <div id='login_dialog' class='hidden'>
          <label>JID:</label><input type='text' id='jid'>
          <label>Password:</label><input type='password' id='password'>
        </div>
      </body>
    </html>

这是 hello.js:

        var Hello = 
        connection: null,
        start_time: null,

        log: function (msg) 
            $('#log').append("<p>" + msg + "</p>");
        ,

        send_ping: function (to) 
            var ping = $iq(
                to: to,
                type: "get",
                id: "ping1").c("ping", xmlns: "urn:xmpp:ping");

            Hello.log("Sending ping to " + to + ".");

            Hello.start_time = (new Date()).getTime();
            Hello.connection.send(ping);
        ,

        handle_pong: function (iq) 
            var elapsed = (new Date()).getTime() - Hello.start_time;
            Hello.log("Received pong from server in " + elapsed + "ms.");

            Hello.connection.disconnect();

            return false;
        
    ;

    $(document).ready(function () 
        $('#login_dialog').dialog(
            autoOpen: true,
            draggable: false,
            modal: true,
            title: 'Connect to XMPP',
            buttons: 
                "Connect": function () 
                    $(document).trigger('connect', 
                        jid: $('#jid').val(),
                        password: $('#password').val()
                    );

                    $('#password').val('');
                    $(this).dialog('close');
                
            
        );
    );

    $(document).bind('connect', function (ev, data) 
        var conn = new Strophe.Connection(
            "http://bosh.metajack.im:5280/xmpp-httpbind");
        conn.connect(data.jid, data.password, function (status) 
            if (status === Strophe.Status.CONNECTED) 
                $(document).trigger('connected');
             else if (status === Strophe.Status.DISCONNECTED) 
                $(document).trigger('disconnected');
            
        );

        Hello.connection = conn;
    );

    $(document).bind('connected', function () 
        // inform the user
        Hello.log("Connection established.");

        Hello.connection.addHandler(Hello.handle_pong, null, "iq", null, "ping1");

        var domain = Strophe.getDomainFromJid(Hello.connection.jid);

        Hello.send_ping(domain);

    );

    $(document).bind('disconnected', function () 
        Hello.log("Connection terminated.");

        // remove dead connection object
        Hello.connection = null;
    );

基本上,它的作用是通过在http://bosh.metajack.im:5280/xmpp-httpbind 运行的 BOSH 服务连接到 XMPP 服务器。连接时,它会使用 jQuery 将“已建立连接”打印到 html 文件。

但是,我无法让它连接到服务器。我检查了http://bosh.metajack.im:5280/xmpp-httpbind 的 bosh 服务是否已启动并正在运行。我在 alpha-labs.net 和 jabber.de 创建了 xmpp 帐户。这两个帐户都在我的 Windows 机器上使用 pidgin IM 工作。但我无法使用此示例登录其中任何一个帐户。

当我输入我的 jid(例如 justastest@alpha-labs.net)和相应的密码时,屏幕上没有任何内容。

我也在这本书的出版商的论坛上发过帖子,但不是很常去,所以我想我会在这里试试。

感谢您的所有帮助!

C

编辑:所以我把它缩小了一点,在其他人的帮助下确定这可能是一个 CORS 问题。到目前为止,我一直在本地的网络浏览器中使用 file:/// 访问 Hello.html。在这种情况下,我无法连接到任何服务器。

但是,如果我在服务器上托管 Hello.html/hello.js,然后通过我的网络浏览器使用 http 访问该版本,那么代码就可以工作,即可以建立服务器连接。

虽然我不太明白,为什么这是一个问题。如果我在本地访问它,为什么它不起作用,我能否以某种方式使其在本地场景中也起作用?

【问题讨论】:

【参考方案1】:

要启用 CORS 功能,您必须从 Web 服务器而不是文件运行本地站点。

Here's a relevant SO answer which explains why。

基本上,因为您网站的来源是文件而不是网址,所以当 CORS 机制尝试确定是否应允许请求时,它会与 null 进行比较。看来这个问题可能只影响某些浏览器(chrome)。显然,简单的解决方法是从本地 Web 服务器运行您的 html 文件。

【讨论】:

以上是关于如果 JS 代码未托管在服务器上(CORS?),Strophejs XMPP Hello World 无法连接到服务器的主要内容,如果未能解决你的问题,请参考以下文章

托管在同一台服务器上的 Django 和 React 的 CORS 问题

Socket.io 未设置 CORS 标头

在哪里启用cors?

使用 MEAN 堆栈应用程序(托管在 Heroku 上)消除 CORS 策略错误

获取 CORS 未获取标题的 Post 问题

未设置 CORS 标头 - 我可以请求图像 url,然后将其返回给自己吗?