php 服务器发送的事件:EventSource引发MIME错误

8ftvxx2r  于 2022-12-17  发布在  PHP
关注(0)|答案(1)|浏览(934)

我第一次尝试使用服务器发送事件。我正在创建一个非常简单的测试:

// sse-test.php
<?php
header("Content-type: text/event-stream");
header("Cache-Control: no-store");

$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
// inside index.html
...
const source = new EventSource("sse_test.php");

// check headers  
fetch('/sse-test.php')
.then(res => {
  for (let value of res.headers.values()) {
    console.log(value)
  }
})

EventSource构造函数抛出了一个EventSource's response has a MIME type ("text/html") that is not "text/event-stream". Aborting the connection错误。我正在记录响应头,它们似乎是正确的,它们包括一个text/event-stream;头。
我错过了什么?

mbyulnm0

mbyulnm01#

您不需要向事件源服务器发送 AJAX 请求-您可以像上面那样使用new EventSource进行连接,但随后将事件处理程序绑定到返回的event-stream
一个完整的基本示例可能会有所帮助。

<?php
    if( isset( $_GET['sse'], $_GET['evt'] ) && $_GET['sse']=='go' ){
        # this script will run infinitely whilst client is connected so no timeout
        set_time_limit( 0 );
        
        # ensure no stray characters in event stream other than those created in the sse function below
        ob_end_clean();

        # repeat the infinite loop after a delay
        $sleep=1;
        
        # the name of the event.. this is sent in the connection url
        $evt=$_GET['evt'];
        
        #utility to send a correctly formatted message
        function sse( $evtname='sse', $data=null, $retry=1000 ){
            if( !is_null( $data ) ){
                echo "event:".$evtname."\r\n";
                echo "retry:".$retry."\r\n";
                echo "data:" . json_encode( $data, JSON_FORCE_OBJECT | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS );
                echo "\r\n\r\n";
            }
        }   
        
        # ensure that this header is set before starting the infinite loop.
        header('Content-Type: text/event-stream');
        while( true ){
            /*
                Do whatever needs to be done - query db,
                query remote api, perform calculations etc
                
                prepare payload to send
            */
            $payload=array(
                'data'      =>  rand( 0, 100 ),
                'date'      =>  date( 'Y-m-d H:i:s' )
            );
            
            #send the packet
            sse( $evt, $payload );
            
            # flush buffers
            if( @ob_get_level() > 0 ) for( $i=0; $i < @ob_get_level(); $i++ ) @ob_flush();
            @flush();
            
            # take it easy for a while before doing it all again.
            sleep( $sleep );
        }
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Welcome!</title>
    </head>
    <body>
    
        <div id="result"></div>
        
        <script>
        
            const evt='SOME_EVENT_NAME';
        
            // single page - connect with querystring parameters
            let sse = new EventSource( '?sse=go&evt='+evt );
            
            // bind the event listener and process response from server.
            sse.addEventListener(evt,e=>{
                console.log(e.data);
                document.getElementById("result").innerHTML=e.data;
            })
        </script>
    </body>
</html>

相关问题