javascriptnode.jsexpressfastify

Verify if response is express or fastify


In NodeJS, using Javascript I have a "res" object that can be either an Express or Fastify response, is there any way to check which of the two is this response?


Solution

  • There are 3 ways to solve this problem: the bad way, the less-awful way, and the way that results in actual clean code.

    1. The bad way: duck typing

    The most intiutive way is using a technique called "duck typing" to tell what kind of object you're dealing with. Look at res, check what properties it has, and infer the type based on that. In particular, you'll be interested in the differences between the objects to be able to tell them apart, so search for special features that the other framework doesn't have.

    Example checks:

    function isExpress(res) {
      return (typeof res === 'object' && typeof res.sendFile === 'function');
    }
    function isFastify(res) {
      return (typeof res === 'object' && typeof res.hasHeader === 'function');
    }
    

    However, there's a problem: what if you get a res that is extended by a middleware for express.js or for fastify, which adds the property? Then, depending on the ordering of your if-elses, you may confuse one for the other.

    2. The less-awful way: decorating the object yourself

    It would be better if we could tell the objects apart regardless of what middlewares are applied - so that a feature being added doesn't break our type recognition logic.

    Instead, we can purposefully extend the res object using a special, additional property, so that it's obvious from looking at that property whether we're dealing with express or fastify. To do this, we need to make sure that:

    Quite literally:

    const FRAMEWORK_TYPE = Symbol('type of framework that res comes from');
    
    expressApp.use(function(req, res, next) {
      res[FRAMEWORK_TYPE] = 'express';
      next();
    });
    
    fastifyApp.decorateReply(FRAMEWORK_TYPE, 'fastify');
    

    Then, you can refer to res[FRAMEWORK_TYPE] and check the hint that you've left for yourself directly.

    3. The clean way: design patterns

    The way you've formulated the original problem is: how to check what type of instance we're dealing with. However, the purpose of this check is most likely to be able to integrate different frameworks (express and fastify) with a single piece of code that does something else (a handler).

    This problem is usually solved with the Adapter design pattern - have a layer that speaks a common API and hides the complexity of having different possible implementations. For instance, say your handler needs the request body and headers, and you need to be able to respond via JSON regardless of framework. Then, you could define the handler signature to be:

    ({ body, headers }) => responseObject
    

    Next, call that handler from both frameworks. You'll notice that you need to refer to different parts of req and res in case of express and fastify in order to call the handler properly. Also, in case of fastify, you'll be able to just Promise.resolve(responseObject), but for express, you may need to do res.json(responseObject) instead.

    This way, you decouple your business logic (handler) from the infrastructure layer (web server).