diff --git a/changelog.d/rustcfml-reportaslucee-detection.fixed.md b/changelog.d/rustcfml-reportaslucee-detection.fixed.md new file mode 100644 index 000000000..44827d3a4 --- /dev/null +++ b/changelog.d/rustcfml-reportaslucee-detection.fixed.md @@ -0,0 +1 @@ +- Engine detection now recognizes RustCFML v0.507+ running in its default `reportAsLucee` mode (where `server.coldfusion.productName` reports "Lucee") by matching the stable `server.lucee.versionName == "RustCFML"` identity marker, so the dedicated RustCFML engine adapter is selected instead of the Lucee adapter and adapter-gated behavior (image-info support, capability probes, engine version gates) routes correctly again. diff --git a/vendor/wheels/events/onapplicationstart.cfc b/vendor/wheels/events/onapplicationstart.cfc index ac58622d0..ad3c01f9f 100644 --- a/vendor/wheels/events/onapplicationstart.cfc +++ b/vendor/wheels/events/onapplicationstart.cfc @@ -538,6 +538,14 @@ component { * branch or RustCFML is misclassified as Lucee and its dedicated engine * adapter becomes dead code. Other probe-verified RustCFML markers: * server.java.vendor = "RustCFML (no JVM)". + * + * As of RustCFML v0.507.0, reportAsLucee defaults to true: the productName + * marker reports "Lucee" (with Lucee's productVersion) and the real engine + * version moves to server.lucee.version behind a Lucee-major prefix + * ("7.0.519.0" means RustCFML 0.519.0). The one field upstream documents + * as the stable identity marker — their own isRustCFML() BIF keys on it — + * is server.lucee.versionName == "RustCFML", so that branch must also run + * BEFORE the Lucee branch. */ public struct function $detectEngine(required struct serverScope) { local.rv = {}; @@ -551,6 +559,14 @@ component { ) { local.rv.serverName = "RustCFML"; local.rv.serverVersion = arguments.serverScope.coldfusion.productVersion; + } else if ( + StructKeyExists(arguments.serverScope, "lucee") + && StructKeyExists(arguments.serverScope.lucee, "versionName") + && arguments.serverScope.lucee.versionName == "RustCFML" + ) { + local.rv.serverName = "RustCFML"; + // Strip the impersonated Lucee major ("7.0.519.0" -> "0.519.0"). + local.rv.serverVersion = ListRest(arguments.serverScope.lucee.version, "."); } else if (StructKeyExists(arguments.serverScope, "lucee")) { local.rv.serverName = "Lucee"; local.rv.serverVersion = arguments.serverScope.lucee.version; diff --git a/vendor/wheels/tests/specs/engineAdapterSpec.cfc b/vendor/wheels/tests/specs/engineAdapterSpec.cfc index 22225db79..3b7521a4b 100644 --- a/vendor/wheels/tests/specs/engineAdapterSpec.cfc +++ b/vendor/wheels/tests/specs/engineAdapterSpec.cfc @@ -203,10 +203,28 @@ component extends="wheels.WheelsTest" { expect(detected.serverVersion).toBe("0.417.0"); }); + it("resolves RustCFML under reportAsLucee impersonation (v0.507+) via the versionName marker", function() { + // As of RustCFML v0.507.0 reportAsLucee defaults to true: + // productName reports "Lucee" with Lucee's productVersion, and + // the real engine version hides behind a Lucee-major prefix in + // server.lucee.version. The stable identity marker upstream + // documents (and keys its own isRustCFML() on) is + // server.lucee.versionName == "RustCFML". + var events = CreateObject("component", "wheels.events.onapplicationstart"); + var fakeServer = { + lucee: {version: "7.0.519.0", versionName: "RustCFML"}, + coldfusion: {productName: "Lucee", productVersion: "2016,0,03,300357"}, + java: {vendor: "RustCFML (no JVM)"} + }; + var detected = events.$detectEngine(serverScope = fakeServer); + expect(detected.serverName).toBe("RustCFML"); + expect(detected.serverVersion).toBe("0.519.0"); + }); + it("resolves Lucee when server.lucee exists without the RustCFML product marker", function() { var events = CreateObject("component", "wheels.events.onapplicationstart"); var fakeServer = { - lucee: {version: "6.2.0.321"}, + lucee: {version: "6.2.0.321", versionName: "Gelert"}, coldfusion: {productName: "Lucee", productVersion: "6.2.0.321"} }; var detected = events.$detectEngine(serverScope = fakeServer);