2016-08-12 99 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

有趣;我會嘗試其中的一些並回復你。現在你已經說過了,我認爲它可能與標題相關,但至少幾天我不會確定,所以我不會接受答案 - 儘管我會在我能夠。 –