From cc35094bb261cb3185def89d745317fa756560ee Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 3 Jun 2025 00:16:17 +0200 Subject: Add API endpoint for extensions (#7576) * Add API endpoint for extensions Useful for https://github.com/FreshRSS/FreshRSS/issues/7572 * Support PATH_INFO Now also support being invoked like `/api/misc.php/Extension%20Name/` * More documentation --- docs/en/admins/10_ServerConfig.md | 2 +- docs/en/developers/03_Backend/05_Extensions.md | 2 + docs/fr/developers/03_Backend/05_Extensions.md | 2 + docs/fr/users/01_Installation.md | 2 +- lib/Minz/ExtensionManager.php | 18 +++++++ p/api/index.php | 14 +++--- p/api/misc.php | 68 ++++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 p/api/misc.php diff --git a/docs/en/admins/10_ServerConfig.md b/docs/en/admins/10_ServerConfig.md index b7f57e61a..07ea147b6 100644 --- a/docs/en/admins/10_ServerConfig.md +++ b/docs/en/admins/10_ServerConfig.md @@ -98,7 +98,7 @@ server { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; # By default, the variable PATH_INFO is not set under PHP-FPM - # But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var! + # But FreshRSS APIs greader.php and misc.php need it. If you have a “Bad Request” error, double check this var! # NOTE: the separate $path_info variable is required. For more details, see: # https://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; diff --git a/docs/en/developers/03_Backend/05_Extensions.md b/docs/en/developers/03_Backend/05_Extensions.md index aeb693cba..db9b03d60 100644 --- a/docs/en/developers/03_Backend/05_Extensions.md +++ b/docs/en/developers/03_Backend/05_Extensions.md @@ -164,6 +164,8 @@ final class HelloWorldExtension extends Minz_Extension The following events are available: +* `api_misc` (`function(): void`): to allow extensions to have own API endpoint + on `/api/misc.php/Extension%20Name/` or `/api/misc.php?ext=Extension%20Name`. * `check_url_before_add` (`function($url) -> Url | null`): will be executed every time a URL is added. The URL itself will be passed as parameter. This way a website known to have feeds which doesn’t advertise it in the header can still be automatically supported. * `entry_auto_read` (`function(FreshRSS_Entry $entry, string $why): void`): Triggered when an entry is automatically marked as read. The *why* parameter supports the rules {`filter`, `upon_reception`, `same_title_in_feed`}. * `entry_auto_unread` (`function(FreshRSS_Entry $entry, string $why): void`): Triggered when an entry is automatically marked as unread. The *why* parameter supports the rules {`updated_article`}. diff --git a/docs/fr/developers/03_Backend/05_Extensions.md b/docs/fr/developers/03_Backend/05_Extensions.md index 728d5c843..6996cee58 100644 --- a/docs/fr/developers/03_Backend/05_Extensions.md +++ b/docs/fr/developers/03_Backend/05_Extensions.md @@ -218,6 +218,8 @@ final class HelloWorldExtension extends Minz_Extension The following events are available: +* `api_misc` (`function(): void`) : permet aux extensions d’avoir leur propre point d’accès API + sur `/api/misc.php/Nom%20Extension/` ou `/api/misc.php?ext=Nom%20Extension`. * `check_url_before_add` (`function($url) -> Url | null`): will be executed every time a URL is added. The URL itself will be passed as parameter. This way a website known to have feeds which doesn’t advertise diff --git a/docs/fr/users/01_Installation.md b/docs/fr/users/01_Installation.md index 85b75fea5..8236776fd 100644 --- a/docs/fr/users/01_Installation.md +++ b/docs/fr/users/01_Installation.md @@ -118,7 +118,7 @@ server { fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.*)$; # Par défaut la variable PATH_INFO n’est pas définie sous PHP-FPM - # or l’API FreshRSS greader.php en a besoin. Si vous avez un “Bad Request”, vérifiez bien cette dernière ! + # mais les APIs FreshRSS greader.php et misc.php en ont besoin. Si vous avez un “Bad Request”, vérifiez bien cette dernière ! # REMARQUE : l’utilisation de la variable $path_info est requis. Pour plus de détails, voir : # https://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; diff --git a/lib/Minz/ExtensionManager.php b/lib/Minz/ExtensionManager.php index fea1f5879..b1d499392 100644 --- a/lib/Minz/ExtensionManager.php +++ b/lib/Minz/ExtensionManager.php @@ -22,6 +22,10 @@ final class Minz_ExtensionManager { * @var array,'signature':'NoneToNone'|'NoneToString'|'OneToOne'|'PassArguments'}> */ private static array $hook_list = [ + 'api_misc' => [ // function(): void + 'list' => [], + 'signature' => 'NoneToNone', + ], 'check_url_before_add' => [ // function($url) -> Url | null 'list' => [], 'signature' => 'OneToOne', @@ -429,4 +433,18 @@ final class Minz_ExtensionManager { call_user_func($function); } } + + /** + * Call a hook which takes no argument and returns nothing. + * Same as callHookVoid but only calls the first extension. + * + * @param string $hook_name is the hook to call. + */ + public static function callHookUnique(string $hook_name): bool { + foreach (self::$hook_list[$hook_name]['list'] ?? [] as $function) { + call_user_func($function); + return true; + } + return false; + } } diff --git a/p/api/index.php b/p/api/index.php index 66c9e465c..fd9828080 100644 --- a/p/api/index.php +++ b/p/api/index.php @@ -28,9 +28,7 @@ echo json_encode([

Google Reader compatible API

Your API address:
-
+
Google Reader API configuration test:
?
@@ -38,12 +36,16 @@ echo Minz_Url::display('/api/greader.php', 'html', true);

Fever compatible API

Your API address:
-
+
Fever API configuration test:
?
+

API for extensions

+
+
Your API address:
+
+
+ diff --git a/p/api/misc.php b/p/api/misc.php new file mode 100644 index 000000000..7724caa7a --- /dev/null +++ b/p/api/misc.php @@ -0,0 +1,68 @@ + 1) { + $extensionName = $pathInfos[1]; + } + } +} + +if ($extensionName === '') { + badRequest(); +} + +Minz_Session::init('FreshRSS', volatile: true); + +FreshRSS_Context::initSystem(); +if ( + !FreshRSS_Context::hasSystemConf() || + !FreshRSS_Context::systemConf()->api_enabled || + empty(FreshRSS_Context::systemConf()->extensions_enabled[$extensionName]) +) { + serviceUnavailable(); +} + +// Only enable the extension that is being called +FreshRSS_Context::systemConf()->extensions_enabled = [$extensionName => true]; +Minz_ExtensionManager::init(); + +Minz_Translate::init(); + +if (!Minz_ExtensionManager::callHookUnique('api_misc')) { + serviceUnavailable(); +} -- cgit v1.2.3