mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-07-16 01:52:53 -04:00
WebSub: ignore http/https scheme difference in Self URL comparison (#9005)
* WebSub: ignore http/https scheme difference in Self URL comparison The PubSubHubbub endpoint logged 'Self URL does not match registered canonical URL' whenever a feed's self URL differed from the registered canonical URL only by http vs https (common with http->https redirects), spamming the log. Compare the URLs ignoring the http/https scheme while still requiring host/path/query to match exactly. Closes #3087 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Stylistic preferences --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
This commit is contained in:
@@ -295,6 +295,14 @@ final class FreshRSS_http_Util {
|
||||
($url1['port'] ?? '') === ($url2['port'] ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 0 if values on either side are equal ignoring the HTTP vs HTTPS differences, or 1/-1 if they differ.
|
||||
*/
|
||||
public static function compareUrlIgnoringHttps(string $url1, string $url2): int {
|
||||
$normalizeScheme = static fn(string $url): string => preg_replace('#^https?://#i', '//', trim($url)) ?? $url;
|
||||
return $normalizeScheme($url1) <=> $normalizeScheme($url2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value for CURLOPT_RESOLVE as an array, null if no allowed IPs were found, false if the domain failed to resolve.
|
||||
*
|
||||
|
||||
@@ -121,14 +121,14 @@ if ($httpLink !== '' && preg_match_all('/<([^>]+)>;\\s*rel="([^"]+)"/', $httpLin
|
||||
// }
|
||||
if (!empty($links['self'])) {
|
||||
$httpSelf = FreshRSS_http_Util::checkUrl($links['self']) ?: '';
|
||||
if ($self !== '' && $self !== $httpSelf) {
|
||||
if ($self !== '' && FreshRSS_http_Util::compareUrlIgnoringHttps($self, $httpSelf) !== 0) {
|
||||
Minz_Log::warning('Warning: Self URL mismatch between XML [' . $self . '] and HTTP!: ' . $httpSelf, PSHB_LOG);
|
||||
}
|
||||
$self = $httpSelf;
|
||||
}
|
||||
}
|
||||
|
||||
if ($self !== $canonical) {
|
||||
if (FreshRSS_http_Util::compareUrlIgnoringHttps($self, $canonical) !== 0) {
|
||||
//header('HTTP/1.1 422 Unprocessable Entity');
|
||||
Minz_Log::warning('Warning: Self URL [' . $self . '] does not match registered canonical URL!: ' . $canonical, PSHB_LOG);
|
||||
//die('Self URL does not match registered canonical URL!');
|
||||
|
||||
41
tests/app/Utils/httpUtilTest.php
Normal file
41
tests/app/Utils/httpUtilTest.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
/**
|
||||
* Tests for FreshRSS_http_Util
|
||||
*/
|
||||
class httpUtilTest extends \PHPUnit\Framework\TestCase {
|
||||
|
||||
#[DataProvider('provideUrlsIgnoringHttps')]
|
||||
public function test_compareUrlIgnoringHttps(string $url1, string $url2, bool $expected): void {
|
||||
self::assertEquals($expected, FreshRSS_http_Util::compareUrlIgnoringHttps($url1, $url2) === 0);
|
||||
}
|
||||
|
||||
/** @return list<array{string,string,bool}> */
|
||||
public static function provideUrlsIgnoringHttps(): array {
|
||||
return [
|
||||
// Only the scheme differs → equal
|
||||
['http://www.blogger.com/feeds/1/posts', 'https://www.blogger.com/feeds/1/posts', true],
|
||||
['https://example.net/feed.xml?a=1&b=2', 'http://example.net/feed.xml?a=1&b=2', true],
|
||||
['HTTP://Example.net/Feed', 'https://Example.net/Feed', true],
|
||||
['HTTPS://Example.net/Feed', 'http://Example.net/Feed', true],
|
||||
|
||||
// Fully identical → equal
|
||||
['https://example.net/feed', 'https://example.net/feed', true],
|
||||
['', '', true],
|
||||
|
||||
// Path differs → not equal (scheme-only tolerance must not hide real mismatches)
|
||||
['http://example.net/a', 'https://example.net/b', false],
|
||||
// Trailing slash is a path difference → not equal
|
||||
['http://example.net/', 'https://example.net', false],
|
||||
// Host differs → not equal
|
||||
['http://a.example.net/feed', 'https://b.example.net/feed', false],
|
||||
// Query differs → not equal
|
||||
['https://example.net/feed?a=1', 'http://example.net/feed?a=2', false],
|
||||
// Non-http(s) schemes are compared as-is
|
||||
['ftp://example.net/feed', 'https://example.net/feed', false],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user