]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Conf] composites: route composites.dynamic to map handler
authorVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 26 May 2026 20:08:45 +0000 (21:08 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Tue, 26 May 2026 20:08:45 +0000 (21:08 +0100)
Add a reserved key in the composites { ... } config block so users can
attach a hot-reloadable map of composites:

    composites {
        STATIC_COMP { expression = "..."; score = 1.0; }
        dynamic = "/etc/rspamd/composites.map";
        # or dynamic = ["http://a/x", "file://y"];
        # or dynamic = { url = "..."; signature = "..."; }
    }

The handler intercepts the 'dynamic' key inside the composites section,
hands the UCL value to rspamd_composites_add_dynamic_map(), and lets
the rest of the section continue with static composite definitions.

Smoke-tested by running rspamd against a config with a file-backed
dynamic map: map_fin fires, the publish pipeline registers the
composites with the symcache, and the dynamic generation bumps to 1.

src/libserver/cfg_rcl.cxx

index 8a472f42469379cb861fc31d0936a3483f51cd99..e3b08c5abd628a2137bcb83b25db7afd497e5ad8 100644 (file)
@@ -1588,14 +1588,29 @@ rspamd_rcl_composites_handler(rspamd_mempool_t *pool,
                                                          struct rspamd_rcl_section *section,
                                                          GError **err)
 {
+       auto *cfg = static_cast<rspamd_config *>(ud);
        auto success = TRUE;
 
        auto it = ucl_object_iterate_new(obj);
        const auto *cur = obj;
 
        while ((cur = ucl_object_iterate_safe(it, true))) {
+               const auto *cur_key = ucl_object_key(cur);
+
+               /* `dynamic` is reserved for hot-reloadable composite map sources.
+                * Its value is whatever rspamd_map_add_from_ucl accepts: a single
+                * URL string, an array of URLs, or a full map UCL object. */
+               if (cur_key != nullptr && strcmp(cur_key, "dynamic") == 0) {
+                       if (!rspamd_composites_add_dynamic_map(cfg->composites_manager, cur, cfg)) {
+                               msg_err_config("failed to register dynamic composites map");
+                               success = FALSE;
+                               break;
+                       }
+                       continue;
+               }
+
                success = rspamd_rcl_composite_handler(pool, cur,
-                                                                                          ucl_object_key(cur), ud, section, err);
+                                                                                          cur_key, ud, section, err);
                if (!success) {
                        break;
                }