瀏覽器同源策略禁止 AJAX 直接請求不同網域 RSS。解法:自架 PHP Proxy 代理請求,前端呼叫同域 Proxy,Proxy 取得遠端 RSS 回傳。
[前端 JS] --AJAX--> [PHP Proxy (bridge/rss.php)] --HTTP--> [遠端 RSS Feed]
▲ │
└------------------ JSON/XML 回傳 -----------------------------------┘
addServer('127.0.0.1', 11211);
$xml = $mem->get($cacheKey);
if ($xml === false) {
// 設定合理超時
$ctx = stream_context_create([
'http' => [
'timeout' => 10,
'user_agent' => 'MyRSSAggregator/1.0 (+https://example.com)',
'follow_location' => 1,
'max_redirects' => 3,
],
'ssl' => ['verify_peer' => true, 'verify_peer_name' => true]
]);
$xml = @file_get_contents($feedUrl, false, $ctx);
if ($xml === false) {
http_response_code(502);
exit('Failed to fetch feed');
}
// 簡易 XML 合法性檢查
if (!str_starts_with(ltrim($xml), 'set($cacheKey, $xml, 300); // 快取 5 分鐘
}
// 輸出
header('Content-Type: application/xml; charset=utf-8');
header('Cache-Control: public, max-age=300');
echo $xml;
// 使用 fetch (現代)
async function loadFeed(feedUrl) {
const proxy = '/bridge/rss.php?feed=' + encodeURIComponent(feedUrl);
const resp = await fetch(proxy);
if (!resp.ok) throw new Error('Proxy error: ' + resp.status);
const text = await resp.text();
const parser = new DOMParser();
const xml = parser.parseFromString(text, 'application/xml');
// 解析 xml...
}
// 或使用 jQuery
$.ajax({
url: '/bridge/rss.php',
data: {feed: feedUrl},
dataType: 'xml',
success: function(xml) { /* 解析 */ }
});
/rss/channel/item - title, link, description, pubDate, guid/feed/entry - title, link[@href], summary/content, updated, idregisterXPathNamespace 或 DOMXPathDateTime::createFromFormat 處理 RFC 822 / ISO 8601getServerSideProps、Nuxt asyncData 伺服端預取