Skip to content

[GridView] Fetch Open Graph images with the FreshRSS HTTP client - #559

Merged
Alkarex merged 1 commit into
FreshRSS:mainfrom
NopeCharon:gridview-og-image-fetch
Oct 27, 2026
Merged

Alkarex merged 1 commit into
FreshRSS:mainfrom
NopeCharon:gridview-og-image-fetch

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

Summary

The optional Thumbnail fetching feature of Grid View downloads the article page with file_get_contents() on an http(s):// URL to look for og:image / twitter:image.
Since FreshRSS 1.30.0, unregister_unsafe_protocols() removes every stream wrapper except file and php, so that call always fails and no thumbnail is ever found, neither in entry_before_insert nor through the asynchronous AJAX endpoint used by grid.js.
This is the same root cause as the one found for the external YouTubeChannel2RssFeed extension in #529.

  • fetch the page with FreshRSS_http_Util::httpGet() (as done by the core favicon lookup), which also brings the system proxy / cURL options, the internal-host (SSRF) checks, Retry-After handling and the HTML cache
  • keep the previous 5-second timeout
  • resolve relative image URLs against the URL reached after redirects
  • FreshRSS_http_Util::httpGet() exists since FreshRSS 1.28.0, so raise compatibility from 1.25.0 to 1.28.0 (README updated as well) and bump the version to 1.1.2

Validation

  • end-to-end on a CLI-bootstrapped FreshRSS edge install (so the stream wrappers are unregistered as in production), against a local test server and INTERNAL_HOST_ALLOWLIST set for it:
    • main: extractOgImage() returns null for every URL
    • this branch: the og:image is found, including through a 301 redirect where a relative images/cover.jpg is now resolved against the redirected page; a 404 page still gives null
    • without the allowlist entry, the internal host is refused by the FreshRSS SSRF check
  • composer run-script php-lint, phpcs, phpstan (with ../FreshRSS)

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.
@Alkarex

Alkarex commented Oct 27, 2026

Copy link
Copy Markdown
Member

Thanks!

@Alkarex
Alkarex merged commit bee3194 into FreshRSS:main Oct 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants