aboutsummaryrefslogtreecommitdiff
path: root/lib/lib_rss.php
diff options
context:
space:
mode:
authorGravatar Inverle <inverle@proton.me> 2025-11-04 12:48:31 +0100
committerGravatar GitHub <noreply@github.com> 2025-11-04 12:48:31 +0100
commit7d4854a0a4f5665db599f18c34035786465639f3 (patch)
treeed69305612249a91080d42e3fe39021cab15dda2 /lib/lib_rss.php
parent5535067f64fe4285b414a48ae6d16b85fb26f97f (diff)
Create separate `Retry-After` files for proxies (#8029)
* Create separate `Retry-After` files for proxies Bad proxies are able to send a false `Retry-After` header and affect the availability of feeds (domain-wide) for other users. This PR starts including the address of the proxy if present in filenames for `Retry-After` to mitigate the issue. * Reduce code changes * Sync SimplePie fork https://github.com/FreshRSS/simplepie/pull/62 --------- Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Diffstat (limited to 'lib/lib_rss.php')
-rw-r--r--lib/lib_rss.php41
1 files changed, 22 insertions, 19 deletions
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index 5e19ec628..e7503ffe4 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -735,7 +735,24 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
cleanCache(CLEANCACHE_HOURS);
}
- if (($retryAfter = FreshRSS_http_Util::getRetryAfter($url)) > 0) {
+ $options = [];
+ $accept = '';
+ $proxy = is_string(FreshRSS_Context::systemConf()->curl_options[CURLOPT_PROXY] ?? null) ? FreshRSS_Context::systemConf()->curl_options[CURLOPT_PROXY] : '';
+ if (is_array($attributes['curl_params'] ?? null)) {
+ $options = sanitizeCurlParams($attributes['curl_params']);
+ $proxy = is_string($options[CURLOPT_PROXY]) ? $options[CURLOPT_PROXY] : '';
+ if (is_array($options[CURLOPT_HTTPHEADER] ?? null)) {
+ // Remove headers problematic for security
+ $options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER],
+ fn($header) => is_string($header) && !preg_match('/^(Remote-User|X-WebAuth-User)\\s*:/i', $header));
+ // Add Accept header if it is not set
+ if (preg_grep('/^Accept\\s*:/i', $options[CURLOPT_HTTPHEADER]) === false) {
+ $options[CURLOPT_HTTPHEADER][] = 'Accept: ' . $accept;
+ }
+ }
+ }
+
+ if (($retryAfter = FreshRSS_http_Util::getRetryAfter($url, $proxy)) > 0) {
Minz_Log::warning('For that domain, will first retry after ' . date('c', $retryAfter) . '. ' . \SimplePie\Misc::url_remove_credentials($url));
return ['body' => '', 'effective_url' => $url, 'redirect_count' => 0, 'fail' => true];
}
@@ -744,7 +761,6 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
syslog(LOG_INFO, 'FreshRSS GET ' . $type . ' ' . \SimplePie\Misc::url_remove_credentials($url));
}
- $accept = '';
switch ($type) {
case 'json':
$accept = 'application/json,application/feed+json,application/javascript;q=0.9,text/javascript;q=0.8,*/*;q=0.7';
@@ -782,6 +798,9 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
//CURLOPT_VERBOSE => 1, // To debug sent HTTP headers
]);
+ curl_setopt_array($ch, $options);
+ curl_setopt_array($ch, FreshRSS_Context::systemConf()->curl_options);
+
$responseHeaders = '';
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function (\CurlHandle $ch, string $header) use (&$responseHeaders) {
if (trim($header) !== '') { // Skip e.g. separation with trailer headers
@@ -790,22 +809,6 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
return strlen($header);
});
- curl_setopt_array($ch, FreshRSS_Context::systemConf()->curl_options);
-
- if (is_array($attributes['curl_params'] ?? null)) {
- $options = sanitizeCurlParams($attributes['curl_params']);
- if (is_array($options[CURLOPT_HTTPHEADER] ?? null)) {
- // Remove headers problematic for security
- $options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER],
- fn($header) => is_string($header) && !preg_match('/^(Remote-User|X-WebAuth-User)\\s*:/i', $header));
- // Add Accept header if it is not set
- if (preg_grep('/^Accept\\s*:/i', $options[CURLOPT_HTTPHEADER]) === false) {
- $options[CURLOPT_HTTPHEADER][] = 'Accept: ' . $accept;
- }
- }
- curl_setopt_array($ch, $options);
- }
-
if (isset($attributes['ssl_verify'])) {
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, empty($attributes['ssl_verify']) ? 0 : 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (bool)$attributes['ssl_verify']);
@@ -838,7 +841,7 @@ function httpGet(string $url, string $cachePath, string $type = 'html', array $a
$body = '';
Minz_Log::warning('Error fetching content: HTTP code ' . $c_status . ': ' . $c_error . ' ' . $url);
if (in_array($c_status, [429, 503], true)) {
- $retryAfter = FreshRSS_http_Util::setRetryAfter($url, $headers['retry-after'] ?? '');
+ $retryAfter = FreshRSS_http_Util::setRetryAfter($url, $proxy, $headers['retry-after'] ?? '');
if ($c_status === 429) {
$errorMessage = 'HTTP 429 Too Many Requests! [' . \SimplePie\Misc::url_remove_credentials($url) . ']';
} elseif ($c_status === 503) {