vercel / micro

Asynchronous HTTP microservices
MIT License
10.59k stars 459 forks source link

How to use #394

Closed higoka closed 5 years ago

higoka commented 5 years ago

How do i use middlewares and handlers on specific route.

For example like this: app.get('/profile/%id%' , middleware, handler)

Is such thing possible with micro?

maximeshr commented 5 years ago

You can use a middleware function on top of your handler.

const custom = fn => (req, res, ...args) => {
    console.log('Hello from custom!');
    return fn(req, res, ...args);
};

And when you call your handler you just have to call custom on it.

From my side, I compose all my global middlewares together with a compose function:

const compose = (...fns) =>
    fns.reduce(
        (f, g) => (...args) => (g ? f(g(...args)) : f(...args)),
        fn => async (...args) => await fn(...args) // eslint-disable-line no-return-await
    );

const lm = fn => (req, res, ...args) => {
    const {url} = req;

    if (['/ping'].includes(url)) {
        return fn(req, res, ...args);
    }

    logreq(req, res); // this will log my request and response using pino.js

    return fn(req, res, ...args);
};

const m = compose(
    lm
);
const dispatch = require('micro-route/dispatch');

const router = dispatch();

const r = prefixed(router)(API_PREFIX, true); 
// small hack we use here because I need to prefix some routes on production 
// - it returns a function that dispatch()
//  const prefixed = router => (prefix, dual = false) => (route, verb, handler) => {
//  if (dual) {
//      router.dispatch(route, verb, handler);
//  }
//
//  router.dispatch(`${prefix}${route}`, verb, handler);
// };

r('/ping', 'GET', status(200)); // returns 200
r('/version', 'GET', version); // returns version of my api
r('/metrics', 'GET', metrics); // returns some prometheus metrics
r('/custom', 'GET', custom(MyHandler.get)); // call my handler and apply custom middleware before

otherwise(router)(status(405)); // for all other routes, I return a 405

As router I use micro-router and define my entrypoint like that:

const entrypoint = micro(m(router));

I hope it will help you ;-)

higoka commented 5 years ago

Thank you for the great example, definitely helped me a lot.