You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何排查Server-Sent Events获取Icecast流JSON元数据失败问题

问题:Icecast流元数据获取公网部署异常

本地开发时,通过HTML、JS、PHP配合获取Icecast流元数据的功能完全正常,但部署到公网服务器后出现以下问题:

  • 初始遇到CORS错误,添加访问控制头后解决,但PHP无法解析Icecast的status-json.xsl数据
  • 已将本地正常工作的file_get_contents替换为curl,但仍无法获取有效数据
  • Icecast子域名位于Apache反向代理后,流可正常播放,且status-json.xsl可通过公网浏览器正常访问
  • Firefox控制台显示PHP接口返回200状态,但输出内容中本该显示元数据的位置只有句号,PHP文件权限为755

HTML代码

<div id="scroll-container">
  <span class="scroll-text" id="scroll-text"><span>
</div>

JavaScript代码

//Get the stream meta from xml
messages = new Array();
if(typeof(EventSource) !== "undefined") {
  var source = new EventSource("https://www.example.com/radio/js/json.php");
  source.onmessage = function(event) {
                    if (messages.length == 2) messages.splice(-1, 1);
                    messages.splice(0, 0, event.data);
                    document.getElementById("scroll-text").innerHTML = messages.join("<br />");
                };
            } else {
                document.getElementById("scroll-text").innerHTML = "Sorry, your browser does not support server-sent events...";
            }

PHP代码

header('Access-Control-Allow-Origin: *');
//header('Access-Control-Allow-Origin: https://www.example.com');
header('Content-Type: application/json');
header('Accept: application/json');
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, 'https://listen.abengnews.com/status-json.xsl');
$json = curl_exec($ch);
curl_close($ch);
//$json = file_get_contents('https://listen.example.com/status-json.xsl');
$obj = json_decode($json);
$retry = 15000;
echo "data:{$obj->icestats->source->server_name}.
retry:{$retry}
 ";
echo "data:{$obj->icestats->source->genre}. Now playing:
retry:{$retry}
";
echo "data:{$obj->icestats->source->title}.
retry:{$retry}
";
echo "data:{$obj->icestats->source->server_description}

retry:{$retry}

";
//$retry = 10000;
flush();

浏览器直接访问status-json.xsl返回的JSON

{
  "icestats": {
    "admin": "me@example.com",
    "host": "listen.example.com",
    "location": "Mississaauga, Ontario",
    "server_id": "Icecast 2.4.4",
    "server_start": "Sun, 21 May 2023 22:35:55 -0400",
    "server_start_iso8601": "2023-05-21T22:35:55-0400",
    "source": {
      "audio_info": "bitrate=128;samplerate=22050;channels=2",
      "bitrate": 128,
      "channels": 2,
      "genre": "News, Reggae",
      "listener_peak": 5,
      "listeners": 1,
      "listenurl": "http://listen.example.com/sounds.mp3",
      "samplerate": 22050,
      "server_description": "News and reggae",
      "server_name": "Example Radio",
      "server_type": "audio/mpeg",
      "server_url": "listen.example.com",
      "stream_start": "Mon, 22 May 2023 11:01:16 -0400",
      "stream_start_iso8601": "2023-05-22T11:01:16-0400",
      "title": "Burning Spear - Foggy Road",
      "dummy": null
    }
  }
}

Firefox控制台响应

XHRGET
https://www.example.com/radio/js/json.php
[HTTP/1.1 200 OK 130295ms]

1 data:.
2 retry:15000
3 data:. Now playing:
4 retry:15000
5 data:.
6 retry:15000
7 data:
8
9 retry:15000
10
11 

排查与修复方案

1. 定位瓶颈的步骤

  • 检查curl请求错误:在PHP中添加curl错误捕获,查看服务器错误日志(如Apache的error.log)确认问题
    $json = curl_exec($ch);
    if(curl_errno($ch)){
        error_log('Curl error: ' . curl_error($ch));
    }
    curl_close($ch);
    
  • 验证JSON解析结果:输出原始JSON内容和解析错误信息,确认是否格式异常
    var_dump($json);
    echo json_last_error_msg();
    
  • 测试服务器网络连通性:通过SSH在公网服务器执行curl https://listen.abengnews.com/status-json.xsl,确认能否正常获取数据

2. 代码修正点

  • 移除重复响应头:删除Content-Type: application/json和Accept: application/json,保留text/event-stream(适配Server-Sent Events)
  • 添加空值保护:避免$obj为空时触发致命错误
  • 优化curl参数:添加超时设置,避免请求挂起;补充SSL验证相关参数(注意安全风险)

修正后的PHP代码:

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

$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_URL, 'https://listen.abengnews.com/status-json.xsl');
$json = curl_exec($ch);

if(curl_errno($ch)){
    error_log('Curl error: ' . curl_error($ch));
    echo "data:Failed to fetch stream data.
retry:15000
";
    curl_close($ch);
    flush();
    exit;
}
curl_close($ch);

$obj = json_decode($json);
$retry = 15000;

$server_name = isset($obj->icestats->source->server_name) ? $obj->icestats->source->server_name : 'Unknown';
$genre = isset($obj->icestats->source->genre) ? $obj->icestats->source->genre : 'Unknown';
$title = isset($obj->icestats->source->title) ? $obj->icestats->source->title : 'Unknown';
$server_desc = isset($obj->icestats->source->server_description) ? $obj->icestats->source->server_description : '';

echo "data:{$server_name}.
retry:{$retry}
";
echo "data:{$genre}. Now playing:
retry:{$retry}
";
echo "data:{$title}.
retry:{$retry}
";
echo "data:{$server_desc}

retry:{$retry}

";
flush();

内容的提问来源于stack exchange,提问作者Mark Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:50:26