Firebase Cloud Functions: Difference between onRequest and onCall
Going through the docs, I encountered:
...you can call functions directly with an HTTP request or a call from the client.
~ source
there (link in the quote) is a mention about functions.https.onCall
.
But in the tutorial here, another function functions.https.onRequest
is used, so which one should I use and why? What is the difference/similarity between them?
Documentation for functions.https
is here.
Solution 1:
The official documentation for those is really helpful, but from the view of an amateur, the described differences were confusing at first.
- Both types, when deployed, are assigned with a unique HTTPS endpoint URL and can be accessed directly.
onCall
-
Can be invoked (and this is also the main purpose) directly from the client app.
functions.httpsCallable('getUser')({uid}) .then(r => console.log(r.data.email))
-
It is implemented with user-provided
data
and automagiccontext
.export const getUser = functions.https.onCall((data, context) => { if (!context.auth) return {status: 'error', code: 401, message: 'Not signed in'} return new Promise((resolve, reject) => { // find a user by data.uid and return the result resolve(user) }) })
- The
context
automagically contains metadata about the request such asuid
andtoken
. - Input
data
andresponse
objects are automatically (de)serialized.
onRequest
- Firebase onRequest Docs
- Serves mostly as an Express API endpoint.
-
It is implemented with express
Request
andResponse
objects.export const getUser = functions.https.onRequest((req, res) => { // verify user from req.headers.authorization etc. res.status(401).send('Authentication required.') // if authorized res.setHeader('Content-Type', 'application/json') res.send(JSON.stringify(user)) })
- Depends on user-provided authorization headers.
- You are responsible for input and response data.
Read more here Is the new Firebase Cloud Functions https.onCall trigger better?
Solution 2:
The main difference between onCall and onRequest for the client is the way they are invoked. when you define a function using onCall e.g.
exports.addMessage = functions.https.onCall((data, context) => {
// ...
return ...
});
you invoke it on the client side using firebase function client SDK e.g.
// on the client side, you need to import functions client lib
// then you invoke it like this:
const addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
});
more info for onCall: https://firebase.google.com/docs/functions/callable
But if you define your function using onRequest e.g.
exports.addMesssage = functions.https.onRequest((req, res) {
//...
res.send(...);
}
you can call it using normal JS fetch API (no need to import firebase functions client lib on the client side) e.g.
fetch('<your cloud function endpoint>/addMessage').then(...)
this is the big difference that you need to consider when deciding on how to define your functions on the server.
more info for onRequest: https://firebase.google.com/docs/functions/http-events