aboutsummaryrefslogtreecommitdiff
path: root/app
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 /app
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 'app')
-rw-r--r--app/Models/Feed.php2
-rw-r--r--app/Models/SimplePieResponse.php5
-rw-r--r--app/Utils/httpUtil.php12
3 files changed, 10 insertions, 9 deletions
diff --git a/app/Models/Feed.php b/app/Models/Feed.php
index fd9177d4e..2a1ec3f63 100644
--- a/app/Models/Feed.php
+++ b/app/Models/Feed.php
@@ -552,7 +552,7 @@ class FreshRSS_Feed extends Minz_Model {
Minz_Exception::ERROR
);
} else {
- if (($retryAfter = FreshRSS_http_Util::getRetryAfter($this->url)) > 0) {
+ if (($retryAfter = FreshRSS_http_Util::getRetryAfter($this->url, $this->proxyParam())) > 0) {
throw new FreshRSS_Feed_Exception('For that domain, will first retry after ' . date('c', $retryAfter) .
'. ' . $this->url(includeCredentials: false), code: 503);
}
diff --git a/app/Models/SimplePieResponse.php b/app/Models/SimplePieResponse.php
index 6e15da24a..27dc41b74 100644
--- a/app/Models/SimplePieResponse.php
+++ b/app/Models/SimplePieResponse.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
final class FreshRSS_SimplePieResponse extends \SimplePie\File
{
#[\Override]
- protected function on_http_response($response): void {
+ protected function on_http_response($response, array $curl_options = []): void {
syslog(LOG_INFO, 'FreshRSS SimplePie GET ' . $this->get_status_code() . ' ' . \SimplePie\Misc::url_remove_credentials($this->get_final_requested_uri()));
if (in_array($this->get_status_code(), [429, 503], true)) {
@@ -15,7 +15,8 @@ final class FreshRSS_SimplePieResponse extends \SimplePie\File
$headers = [];
}
- $retryAfter = FreshRSS_http_Util::setRetryAfter($this->get_final_requested_uri(), $headers['retry-after'] ?? '');
+ $proxy = is_string($curl_options[CURLOPT_PROXY] ?? null) ? $curl_options[CURLOPT_PROXY] : '';
+ $retryAfter = FreshRSS_http_Util::setRetryAfter($this->get_final_requested_uri(), $proxy, $headers['retry-after'] ?? '');
if ($retryAfter > 0) {
$domain = parse_url($this->get_final_requested_uri(), PHP_URL_HOST);
if (is_string($domain) && $domain !== '') {
diff --git a/app/Utils/httpUtil.php b/app/Utils/httpUtil.php
index 2b57b410f..6e176a0d3 100644
--- a/app/Utils/httpUtil.php
+++ b/app/Utils/httpUtil.php
@@ -5,7 +5,7 @@ final class FreshRSS_http_Util {
private const RETRY_AFTER_PATH = DATA_PATH . '/Retry-After/';
- private static function getRetryAfterFile(string $url): string {
+ private static function getRetryAfterFile(string $url, string $proxy): string {
$domain = parse_url($url, PHP_URL_HOST);
if (!is_string($domain) || $domain === '') {
return '';
@@ -14,7 +14,7 @@ final class FreshRSS_http_Util {
if (is_int($port)) {
$domain .= ':' . $port;
}
- return self::RETRY_AFTER_PATH . urlencode($domain) . '.txt';
+ return self::RETRY_AFTER_PATH . urlencode($domain) . (empty($proxy) ? '' : ('_' . urlencode($proxy))) . '.txt';
}
/**
@@ -39,11 +39,11 @@ final class FreshRSS_http_Util {
* Check whether the URL needs to wait for a Retry-After period.
* @return int The timestamp of when the Retry-After expires, or 0 if not set.
*/
- public static function getRetryAfter(string $url): int {
+ public static function getRetryAfter(string $url, string $proxy): int {
if (rand(0, 30) === 1) { // Remove old files once in a while
self::cleanRetryAfters();
}
- $txt = self::getRetryAfterFile($url);
+ $txt = self::getRetryAfterFile($url, $proxy);
if ($txt === '') {
return 0;
}
@@ -61,8 +61,8 @@ final class FreshRSS_http_Util {
/**
* Store the HTTP Retry-After header value of an HTTP `429 Too Many Requests` or `503 Service Unavailable` response.
*/
- public static function setRetryAfter(string $url, string $retryAfter): int {
- $txt = self::getRetryAfterFile($url);
+ public static function setRetryAfter(string $url, string $proxy, string $retryAfter): int {
+ $txt = self::getRetryAfterFile($url, $proxy);
if ($txt === '') {
return 0;
}