nitro icon indicating copy to clipboard operation
nitro copied to clipboard

Middleware registered in plugins is never executed

Open FeldrinH opened this issue 3 years ago • 9 comments

Environment

nitropack v0.5.4, no extra config

Reproduction

Given the following plugin:

// plugins/test.ts
export default defineNitroPlugin(nitroApp => {
    nitroApp.h3App.use('/', () => console.log('Middleware ran'))
    console.log('Plugin registered')
})

The plugin appears to register correctly ('Plugin registered' is printed), but the middleware added with h3App.use is never executed ('Middleware ran' is never printed when navigating to any route).

Describe the bug

Any middleware added inside a nitro plugin with nitroApp.h3App.use or other related methods is never executed. This might be an intentional / known limitation of how plugins work, but it feels unexpected, given that the method throws no error and is readily accessible.

Additional context

No response

Logs

No response

FeldrinH avatar Oct 08 '22 16:10 FeldrinH

See https://github.com/unjs/nitro/pull/302 and https://github.com/nuxt/nuxt.js/issues/14177.

danielroe avatar Oct 09 '22 14:10 danielroe

Those issues appear to be about adding new routes, not middleware. Unless there is some way to add middleware directly to the router that I'm unaware of, I don't really get why this issue was closed.

FeldrinH avatar Oct 09 '22 15:10 FeldrinH

I spent all day to figure out how to add middleware via module and didn't find a solution. The problem is actual.

affinage-digital avatar Dec 04 '22 17:12 affinage-digital

Hello, Does anyone have a way to add a middleware to nitro yet?

Have a great day.

EDIT: To be more precise, I need to resolve CORS issues and can't really do that efficiently right now so I am trying to use https://github.com/NozomuIkuta/h3-cors.

ColinEspinas avatar Jan 27 '23 17:01 ColinEspinas

This worked for me

export default defineNitroPlugin(nitroApp => {
  nitroApp.h3App.stack.unshift({
    route: "/",
    handler: () => {
      console.log('middlware ran');
    },
  });
})

Botz avatar Feb 17 '23 11:02 Botz

./server/plugins/code.ts

export default defineNitroPlugin(async nitroApp => {
    const handler = await createWebhook();

    nitroApp.h3App.stack.unshift({
        route: '/',
        handler: fromNodeMiddleware(handler),
    });
});

affinage-digital avatar Feb 17 '23 11:02 affinage-digital

This worked for me

export default defineNitroPlugin(nitroApp => {
  nitroApp.h3App.stack.unshift({
    route: "/",
    handler: () => {
      console.log('middlware ran');
    },
  });
})

I suppose that works, but it reverses the intuitive order - middlewares that are registered first are now run after middlewares that are registered later.

FeldrinH avatar Feb 17 '23 13:02 FeldrinH

Thank you for providing a way to solve this. I had been searching for a solution all day.

ananthachetan avatar Mar 28 '23 14:03 ananthachetan

I need to catch a route like /@:username/ and bypass all not starting with @. Does nitro provide something like event.next()? to continue the route matching?

shtse8 avatar Mar 10 '24 23:03 shtse8

I need to catch a route like /@:username/ and bypass all not starting with @.

Supporting paterns in same segment of routes will be coming with next major version of h3/radix3/nitro to allow this 🤞🏼


Generally please avoid modifying nitroApp.h3App.stack, it is unsafe and error-prune and usually the routing patterns could be designed better to avoid requiring workarounds like this. if you have any questions feel free to use Discussions 🙏🏼

pi0 avatar May 16 '24 21:05 pi0

Wait what is the resolution of the original issue? Is there now a supported way to add middleware in a plugin?

FeldrinH avatar May 16 '24 21:05 FeldrinH

@FeldrinH No and you should not register middleware inside a runtime plugin (it is unstable and unpredictable). Middleware should be registered via server/middleware directory or handlers: [{ middleware: true, handler: 'path to handler' }] from configuration to register middleware.

There is a new way of using hooks (request, beforeResponse and afterResponse) which request runs before any other middleware.

export default defineNitroPlugin(nitroApp => {
  nitroApp.hooks.hook('request', (event) => {})
  nitroApp.hooks.hook('afterResponse', (event) => {})
})

Please use Discussions if you have a case that would not be solved with hooks either.

pi0 avatar May 16 '24 21:05 pi0

Fair enough

FeldrinH avatar May 16 '24 22:05 FeldrinH