mirror of
https://github.com/FreshRSS/Extensions.git
synced 2026-11-04 10:48:40 +00:00
[GridView] Fetch Open Graph images with the FreshRSS HTTP client (#559)
The optional Open Graph thumbnail fetching downloaded article pages with file_get_contents() on an http(s) URL. Since FreshRSS 1.30.0, every stream wrapper except file:// and php:// is unregistered at startup, so that call always fails and no og:image / twitter:image is ever found, both when entries are inserted and through the asynchronous AJAX endpoint. Use FreshRSS_http_Util::httpGet() instead, like the core favicon lookup. It goes through cURL and also applies the system proxy and cURL options, the internal-host (SSRF) checks, Retry-After handling and the HTML cache. The previous 5-second timeout is kept, and relative image URLs are now resolved against the URL reached after redirects. FreshRSS_http_Util::httpGet() exists since FreshRSS 1.28.0, so raise the declared compatibility accordingly and bump the version to 1.1.2.
This commit is contained in:
1 parent
0a0c2c2655
commit
bee3194ea0
3 files changed
+13
-26
No files matched your search
@@ -60,7 +60,7 @@ Your grid view preference is saved locally and persists across sessions.
|
||||
|
||||
## Requirements
|
||||
|
||||
- FreshRSS 1.20.0 or later
|
||||
- FreshRSS 1.28.0 or later
|
||||
|
||||
## Responsive Breakpoints
|
||||
|
||||
|
||||
@@ -430,43 +430,30 @@ final class GridViewExtension extends Minz_Extension {
|
||||
/**
|
||||
* Fetch a URL and extract the og:image meta tag.
|
||||
*
|
||||
* @param string $url The article URL to fetch
|
||||
* @param non-empty-string $url The article URL to fetch
|
||||
* @return string|null The og:image URL or null if not found
|
||||
*/
|
||||
private function extractOgImage(string $url): ?string {
|
||||
$ctx = stream_context_create([
|
||||
'http' => [
|
||||
'timeout' => 5,
|
||||
'method' => 'GET',
|
||||
'header' => "User-Agent: FreshRSS/GridView\r\n",
|
||||
'follow_location' => 1,
|
||||
'max_redirects' => 3,
|
||||
'ignore_errors' => true,
|
||||
],
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_peer_name' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
// Only fetch the first 50 KB — og:image is in <head>
|
||||
$html = @file_get_contents($url, false, $ctx, 0, 50000);
|
||||
if ($html === false || $html === '') {
|
||||
// Use the FreshRSS HTTP client, as FreshRSS 1.30+ disables the http(s) stream wrappers
|
||||
['body' => $html, 'effective_url' => $effectiveUrl, 'fail' => $fail] = FreshRSS_http_Util::httpGet($url,
|
||||
cachePath: CACHE_PATH . '/' . sha1($url) . '.html', type: 'html', attributes: ['timeout' => 5]);
|
||||
if ($fail || $html === '') {
|
||||
return null;
|
||||
}
|
||||
$pageUrl = $effectiveUrl ?: $url;
|
||||
|
||||
// Try og:image first, then twitter:image (both attribute orderings)
|
||||
if (preg_match('/<meta\s[^>]*property=["\']og:image["\'][^>]*content=["\']([^"\']+)["\']/i', $html, $matches)) {
|
||||
return $this->normalizeImageUrl($matches[1], $url);
|
||||
return $this->normalizeImageUrl($matches[1], $pageUrl);
|
||||
}
|
||||
if (preg_match('/<meta\s[^>]*content=["\']([^"\']+)["\'][^>]*property=["\']og:image["\']/i', $html, $matches)) {
|
||||
return $this->normalizeImageUrl($matches[1], $url);
|
||||
return $this->normalizeImageUrl($matches[1], $pageUrl);
|
||||
}
|
||||
if (preg_match('/<meta\s[^>]*name=["\']twitter:image["\'][^>]*content=["\']([^"\']+)["\']/i', $html, $matches)) {
|
||||
return $this->normalizeImageUrl($matches[1], $url);
|
||||
return $this->normalizeImageUrl($matches[1], $pageUrl);
|
||||
}
|
||||
if (preg_match('/<meta\s[^>]*content=["\']([^"\']+)["\'][^>]*name=["\']twitter:image["\']/i', $html, $matches)) {
|
||||
return $this->normalizeImageUrl($matches[1], $url);
|
||||
return $this->normalizeImageUrl($matches[1], $pageUrl);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "Grid View",
|
||||
"author": "Marius Stroe <https://github.com/mstroe>",
|
||||
"description": "A grid/card view for displaying feeds with images, configurable 2-4 columns, FreshRSS native share integration, and browser reader mode support",
|
||||
"version": "1.1.1",
|
||||
"version": "1.1.2",
|
||||
"entrypoint": "GridView",
|
||||
"type": "user",
|
||||
"compatibility": "1.25.0"
|
||||
"compatibility": "1.28.0"
|
||||
}
|
||||
Reference in new issue
Block a user