Kevin Danikowski
Kevin Danikowski

Reputation: 5196

Add middleware to all firebase functions in one line / function

In express you can add middleware such as app.use(cors()) which adds it to all of the endpoints, however I can't find something similar in firebase examples. Here is the example (see below) of how to apply it in every function. However I want to apply the middleware (cors or other) globally, as I have many functions.

import * as cors from 'cors';
const corsHandler = cors({origin: true});

export const exampleFunction= functions.https.onRequest(async (request, response) => {
       corsHandler(request, response, () => { return handler(req, res) });
});

What is the equivalent of app.use() in firebase? Is adding and express server the only option?

Upvotes: 10

Views: 6086

Answers (3)

Jeong Yo Han
Jeong Yo Han

Reputation: 600

Here is a way in which you can add a middleware function to the controller itself as a one-liner. In this case, the useMiddleware() is the middleware line.

const useMiddleware = async (
    req,
    res,
    ...funcs
) => {
    // note: runMiddlewareFunctions could use some clean up
    const runMiddlewareFunctions = async (req , res, ...funcs)  => {
        let called = false
        if (funcs.length == 0) return;

        const val = await (funcs[0](req, res, async () => {
            called = true
            await runMiddlewareFunctions(req, res, ...funcs.slice(1))
        }))
        if (!called && val == undefined) {
            await runMiddlewareFunctions(req, res, ...funcs.slice(1))
        }
    }

    runMiddlewareFunctions(req, res, ...funcs)
}

const middleware = (req, res, next) => {
   if (!req.body) return res.status(403).send('-_-');
   console.log('hi');
   next();
}

const middleware2 = async (req, res) => {
   console.log('hi2');
}

const middleware3 = (req, res) => {
   console.log("hi3");
}


functions.https.myFunction(async (request, response) => {
  useMiddleware(req, res, middleware1, middleware2, middleware3); 

  // your controller
})

Upvotes: 0

Kevin Danikowski
Kevin Danikowski

Reputation: 5196

Use currying to create a handler, you have to repeat it across all the functions, but it's easier than writing the middleware each time:

const applyMiddleware = handler => (req, res) => {
  return cors(req, res, () => {
    return handler(req, res)
  })
}
exports.handler = functions.https.onRequest(applyMiddleware(yourHandler))

Edit, an example of a more complex middleware:

const applyMiddleware =
  (handler, { authenticatedRoute = false } = {}) =>
  (req, res) => {
    if (authenticatedRoute) {
      const isAuthorized = isAuthenticated(req)
      if (!isAuthorized) {
        return res.status(401).send('Unauthorized')
      }
    }
    return cors(req, res, () => {
      return handler(req, res)
    })
  }
exports.handler = functions.https.onRequest(
   applyMiddleware(yourHandler, { authenticatedRoute: true })
)

Upvotes: 15

Ian Engelbrecht
Ian Engelbrecht

Reputation: 185

import cors from 'cors'

const corsHandler = cors({origin: true});
const applyCORS = handler => (req, res) => {
  return corsHandler(req, res, _ => {
    return handler(req, res)
  })
}

export const firebasefunc = functions.https.onRequest(applyCORS(myhandler))

Upvotes: 2

Related Questions