2016-08-12 102 views
1

我并不负责Apache的配置,所以我不确定我可以提供哪些有用的conf文本,但我相当肯定我有将问题缩小到登录。 EventSource在XAMPP上本地完美工作,无需任何登录,并且在生产服务器上进行身份验证后刷新页面,但服务器上的第一次加载只是不会打开连接。有没有人见过这个问题?在搜索过去几天之后,我在网上找不到任何东西JavaScript的EventSource在Apache基础验证后不会打开连接

编辑:一些代码

一些服务器端代码(这主要是不应该是相关的):

header('Content-Type: text/event-stream'); 
header('Cache-Control: no-cache'); 

$client_stream = new RedisStream(); 
$client_stream->poll(1); //The loop, with sleep time as a parameter 

中的JavaScript:

var xhttpViewSet; 
var xhttpSearch; 
var view = 'tile'; 
var search = ''; 

var seed_url = '/core/seed_view.php'; 
var stream_url = '/core/stream.php'; 

var default_class = 'panel-default'; 
var success_class = 'panel-success'; 
var warning_class = 'panel-warning'; 
var danger_class = 'panel-danger'; 

function UpdateClient(c_name, c_obj) { 
    if ((c_element = document.getElementById(c_name)) !== null) { 
     c_element.classList.remove('text-muted'); 

     c_element.classList.remove(default_class); 
     c_element.classList.remove(success_class); 
     c_element.classList.remove(warning_class); 
     c_element.classList.remove(danger_class); 

     switch (c_obj['status']) { 
      case 0: 
       c_obj['status'] = 'OK'; 
       c_element.classList.add(success_class) 
       break; 
      case 1: 
       c_obj['status'] = 'Warning'; 
       c_element.classList.add(warning_class) 
       break; 
      case 2: 
       c_obj['status'] = 'Critical'; 
       c_element.classList.add(danger_class) 
       break; 
      default: 
       c_obj['status'] = 'Unknown'; 
       c_element.classList.add(danger_class) 
       break; 
     } 

     for (i in c_obj) { 
      var var_nodes = c_element.getElementsByClassName(i); 
      if (var_nodes.length > 0) { 
       for (var j = var_nodes.length - 1; j >= 0; j--) { 
        var_nodes[j].innerHTML = c_obj[i]; 
       } 
      } 
     } 
    } 
} 

function SetView() { 
    var view_url = seed_url + '?search=' + search + '&view=' + view; 

    xhttpViewSet.open('GET', view_url, true); 
    xhttpViewSet.send(); 
} 

var main = function() { 
    container = document.getElementById('content'); 

    if (new XMLHttpRequest()) { 
     xhttpViewSet = new XMLHttpRequest(); 
     xhttpSearch = new XMLHttpRequest(); 
    } else { 
     xhttpViewSet = new ActiveXObject('Microsoft.XMLHTTP'); 
     xhttpSearch = new ActiveXObject('Microsoft.XMLHTTP'); 
    } 

    var stream = new EventSource(stream_url); 
    stream.onopen = function() { 
     console.log('Connection opened.'); //This doesn't fire 
    } 

    stream.onmessage = function(e) { 
     var c_obj = JSON.parse(e.data); 
     UpdateClient(c_obj.name, c_obj.value); 
    }; 

    xhttpViewSet.onreadystatechange = function() { 
     if (xhttpViewSet.readyState == 4) { 
      var resp = xhttpViewSet.responseText; 
      if (xhttpViewSet.status == 200 && resp.length > 0) { 
       container.innerHTML = resp; 
       if (view == 'list') { 
        $('#computer-table').DataTable({ 
         "lengthMenu": [[25, 50, 100], [25, 50, 100]] 
        }); 
       } 
      } else { 
       container.innerHTML = '<error>No computers matched your search or an error occured.</error>'; 
      } 
     } 
    } 
    SetView(); //This successfully does all but make the EventSource connection, and only fails to do that on first load 

    document.getElementById('list-view').addEventListener('click', function() { 
     view = 'list'; 
     SetView(); 
    }); 

    document.getElementById('tile-view').addEventListener('click', function() { 
     view = 'tile'; 
     SetView(); 
    }); 

    document.getElementById('search').addEventListener('keyup', function() { 
     search = this.value.toUpperCase(); 
     SetView(); 
    }); 

    document.getElementById('clear-search').addEventListener('click', function() { 
     document.getElementById('search').value = ''; 
     search = ''; 
     SetView(); 
    }); 
}; 

window.onload = main; 
+0

你将需要提供一些更多的细节。例如客户端代码,服务器代码,您使用的URL ......继续下去。其实,更重要的是:你在控制台中看到了什么?使用开发人员工具至少在两个浏览器中进行测试。请注意重定向发生了什么,发送了什么头文件等。 –

+0

@DarrenCook我将更新以包含前端和后端代码,但至于控制台中发生了什么:此刻没有什么有趣的内容。对于简单的调试和连接计数,我一直在记录“连接打开。“,并且登录后不会立即显示,所以我怀疑它是”onopen“不工作或创建EventSource对象本身;它是 - 并且应该仍然是 - 按原样工作 –

+0

您是否使用PHP会话除了登录之外,生产系统和本地XAMPP系统还有什么不同呢? 至于调试控制台中的“无关紧要”,所有可能的结果都很有趣:例如,您看到auth头文件被发送,它告诉你一件事,或者你没有看到它,它告诉你另一件事:-) –

回答

1

这是一个有点很难知道肯定没有太多的信息,但根据你所说的话到目前为止,我认为它是其中之一:

头部/选项:在发送GET或POST之前,某些浏览器会向服务器脚本发送HEAD或OPTIONS http调用。发送OPTIONS的目的是要询问哪些头允许发送。这可能是登录过程的一部分;那可能会解释为什么它重新加载时工作。有关更多详细信息,请参阅使用HTML5 SSE推送应用程序的第9章(免责声明:我的书)。基本上,在您的SSE脚本的顶部,您需要检查$_SERVER["REQUEST_METHOD"]的值,如果它是"OPTIONS",则拦截并说明您想要接受的标题。我用这一个前:

header("Access-Control-Allow-Headers: Last-Event-ID,". 
    " Origin, X-Requested-With, Content-Type, Accept,". 
    " Authorization");` 

CORS:的HTML页面的URL和页面SSE URL必须具有相同的起源。有关HTML5 SSE(再次)的数据推送应用程序第9章或(较不特别)Wikipedia的详细解释(特定于SSE)。如果这是问题,请考虑将header("Access-Control-Allow-Origin: *");添加到您的SSE脚本。

withCredentials:有上交所构造第二个参数,并使用它像这样:var stream = new EventSource(stream_url, { withCredentials: true });它说这是正常发送身份验证凭据。 (同样,本书的第9章将更详细地描述 - 对重复的插件感到抱歉!)在服务器端还有第二步:在PHP SSE脚本的顶部,您需要添加以下内容。

header("Access-Control-Allow-Origin: "[email protected]$_SERVER["HTTP_ORIGIN"]); 
header("Access-Control-Allow-Credentials: true"); 

PHP会话锁定:这通常会导致相反的问题,这是上证所脚本已锁定PHP会议,所以没有其他的PHP脚本。有关如何处理,请参见https://stackoverflow.com/a/30878764/841830。 (无论如何,这是一个好主意,即使这不是你的问题。)

+0

有趣;我会尝试其中的一些并回复你。现在你已经说过了,我认为它可能与标题相关,但至少几天我不会确定,所以我不会接受答案 - 尽管我会在我能够。 –