JavaScript的EventSource在Apache基础验证后不会打开连接
我并不负责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;
这是一个有点很难知道肯定没有太多的信息,但根据你所说的话到目前为止,我认为它是其中之一:
头部/选项:在发送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://*.com/a/30878764/841830。 (无论如何,这是一个好主意,即使这不是你的问题。)
有趣;我会尝试其中的一些并回复你。现在你已经说过了,我认为它可能与标题相关,但至少几天我不会确定,所以我不会接受答案 - 尽管我会在我能够。 –
你将需要提供一些更多的细节。例如客户端代码,服务器代码,您使用的URL ......继续下去。其实,更重要的是:你在控制台中看到了什么?使用开发人员工具至少在两个浏览器中进行测试。请注意重定向发生了什么,发送了什么头文件等。 –
@DarrenCook我将更新以包含前端和后端代码,但至于控制台中发生了什么:此刻没有什么有趣的内容。对于简单的调试和连接计数,我一直在记录“连接打开。“,并且登录后不会立即显示,所以我怀疑它是”onopen“不工作或创建EventSource对象本身;它是 - 并且应该仍然是 - 按原样工作 –
您是否使用PHP会话除了登录之外,生产系统和本地XAMPP系统还有什么不同呢? 至于调试控制台中的“无关紧要”,所有可能的结果都很有趣:例如,您看到auth头文件被发送,它告诉你一件事,或者你没有看到它,它告诉你另一件事:-) –