On top of setting the Cache-Control header, you can utilize the benefits of global variables setup in your Cloud Functions instances, see Cloud Functions Tips where they mention "Use global variables to reuse objects in future invocations".
With that idea, I am able to use the npm package treasury (yes I did develop this but that is unrelated to the fact that it happens to work with this use case in Cloud Functions - also I use it in production if it makes you feel better).
Example that will utilize the "Memory" adapter of Treasury to store data as long as the variable treasury
exists, which lives and dies with the Cloud Function instance:
const functions = require('firebase-functions');
const tauist = require('tauist');
const Treasury = require('treasury');
const cors = require('cors')({
origin: true
});
// note that memory adapter uses MS not S for ttl
const treasury = new Treasury({
ttl: tauist.ms.thirtyMinutes
});
function getAnimalData({name}) {
// replace this with your actual Promise code doing the "real work" that you want to cache
return new Promise();
}
exports.animal = functions.https.onRequest((req, res) => {
if (req.method !== 'GET') {
return res.status(403).send('Forbidden');
}
// Enable CORS using the `cors` express middleware.
return cors(req, res, () => {
// Reading ticker symbol from URL query parameter.
let name = (req.query.name || '').trim();
console.log('animal name:', name);
if (!name) {
return res.status(400).send('Bad Request');
}
res.set('Cache-Control', `public, max-age=${tauist.s.thirtyMinutes}, s-maxage=${tauist.s.thirtyMinutes}`);
treasury.invest(getAnimalData, {name})
.then((data) => res.status(200).send(data))
.catch((error) => {
console.error('error caught:', error);
res.status(500).send('Internal Server Error');
});
});
});