You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Plugins cannot register middleware with the middleware pipeline (#1906). A plugin that needs request-level behavior (auth checks, CORS, rate limiting) must inject into controller scopes via mixins — the wrong abstraction level.
Proposed API
Via onPluginLoad
function onPluginLoad(app) {
app.addMiddleware("plugins.myPlugin.MyMiddleware");
}
Enable plugins to register middleware with the existing middleware pipeline (Pipeline.cfc) via onPluginLoad(app) or plugin.json, so plugins that need request-level behavior (auth, CORS, rate limiting) can use the proper middleware abstraction instead of controller-scope mixin hacks.
Merit Assessment
Recommendation: Proceed
Correct abstraction level: Request-level concerns (authentication, CORS, logging) belong in middleware, not controller mixins. Today, plugins that need this inject functions into every controller via StructAppend — this is both wasteful and semantically wrong.
Pipeline already supports it:Dispatch.cfc:16-37 builds the middleware pipeline from application.$wheels.middleware (or application.wheels.middleware), accepting both CFC path strings and pre-instantiated objects. Appending plugin-declared middleware to this array is trivial.
Clean integration point via onPluginLoad: The app.addMiddleware() API proposed in the issue maps naturally to pushing entries onto application.$wheels.middleware during the load phase.
plugin.json path works too: Declarative middleware in the manifest can be resolved during $pluginMetaData() and collected for later registration.
app.addMiddleware = function(required any middleware) {
ArrayAppend(application.$wheels.middleware, arguments.middleware);
};
Collect middleware from plugin.json — In $pluginMetaData() (Plugins.cfc:184-196), if the manifest has a middleware array, resolve each entry to a full component path relative to the plugin directory and append to a variables.$class.pluginMiddleware array.
Register collected middleware in onapplicationstart.cfc — After plugin loading (line 237) and before Dispatch creation (line 256), append any plugin-declared middleware to application.$wheels.middleware:
if (StructKeyExists(application.$wheels.PluginObj, "getPluginMiddleware")) {
ArrayAppend(application.$wheels.middleware, application.$wheels.PluginObj.getPluginMiddleware(), true);
}
This ensures plugin middleware is in the pipeline when Dispatch.$init() calls $buildMiddlewarePipeline().
Ordering: Plugin middleware appends after any middleware declared in config/settings.cfm (which sets application.$wheels.middleware at line 91). Plugin load order (alphabetical by default) determines plugin middleware order. Document this clearly.
Tests — Create a test plugin with middleware, verify it appears in Pipeline.getMiddleware() after bootstrap, verify its handle() is called during dispatch.
Estimated complexity: Small (1-2 days, assuming #1979 lands first).
Bootstrap ordering is favorable: Middleware array is initialized at line 91, plugins load at line 237, Dispatch (which builds the pipeline) is created at line 256. Plugin middleware will naturally land between app-level middleware and pipeline construction.
Ordering control: The issue notes "order follows plugin load order" (alphabetical). For most cases this is fine, but consider adding an optional priority field for middleware that must run first/last. This can be deferred to a follow-up.
Route-scoped plugin middleware: The current proposal only covers global middleware. Route-scoped middleware (via mapper.scope(middleware=[...])) would require plugins to register routes first — coordinate with Plugin lifecycle hooks: onPluginLoad, onPluginActivate #1979's bootstrap ordering discussion.
Breaking change risk: None.
Automated analysis by @claude — review and adjust as needed.
Implemented: $processManifestMiddleware() reads middleware array from plugin.json/package.json. Also supported via onPluginLoad(app) with app.registerMiddleware(). Tested in PluginMiddlewarePipelineSpec.cfc.
Activity
bpamiri commentedon Mar 16, 2026
Analysis
Synopsis
Enable plugins to register middleware with the existing middleware pipeline (
Pipeline.cfc) viaonPluginLoad(app)orplugin.json, so plugins that need request-level behavior (auth, CORS, rate limiting) can use the proper middleware abstraction instead of controller-scope mixin hacks.Merit Assessment
Recommendation: Proceed
StructAppend— this is both wasteful and semantically wrong.Dispatch.cfc:16-37builds the middleware pipeline fromapplication.$wheels.middleware(orapplication.wheels.middleware), accepting both CFC path strings and pre-instantiated objects. Appending plugin-declared middleware to this array is trivial.onPluginLoad: Theapp.addMiddleware()API proposed in the issue maps naturally to pushing entries ontoapplication.$wheels.middlewareduring the load phase.plugin.jsonpath works too: Declarative middleware in the manifest can be resolved during$pluginMetaData()and collected for later registration.Implementation Plan
Add
addMiddleware()to the app context struct (Plugin lifecycle hooks: onPluginLoad, onPluginActivate #1979'sonPluginLoad(app)context). This method appends a CFC path or instance toapplication.$wheels.middleware:Collect middleware from
plugin.json— In$pluginMetaData()(Plugins.cfc:184-196), if the manifest has amiddlewarearray, resolve each entry to a full component path relative to the plugin directory and append to avariables.$class.pluginMiddlewarearray.Register collected middleware in
onapplicationstart.cfc— After plugin loading (line 237) and before Dispatch creation (line 256), append any plugin-declared middleware toapplication.$wheels.middleware:This ensures plugin middleware is in the pipeline when
Dispatch.$init()calls$buildMiddlewarePipeline().Ordering: Plugin middleware appends after any middleware declared in
config/settings.cfm(which setsapplication.$wheels.middlewareat line 91). Plugin load order (alphabetical by default) determines plugin middleware order. Document this clearly.Tests — Create a test plugin with middleware, verify it appears in
Pipeline.getMiddleware()after bootstrap, verify itshandle()is called during dispatch.Estimated complexity: Small (1-2 days, assuming #1979 lands first).
Dependencies & Risks
onPluginLoad(app)is the primary registration mechanism.middlewarekey.priorityfield for middleware that must run first/last. This can be deferred to a follow-up.mapper.scope(middleware=[...])) would require plugins to register routes first — coordinate with Plugin lifecycle hooks: onPluginLoad, onPluginActivate #1979's bootstrap ordering discussion.Automated analysis by @claude — review and adjust as needed.
bpamiri commentedon Mar 26, 2026
Implemented:
$processManifestMiddleware()readsmiddlewarearray from plugin.json/package.json. Also supported viaonPluginLoad(app)withapp.registerMiddleware(). Tested in PluginMiddlewarePipelineSpec.cfc.