Los SDK de cliente de Cloud Functions para Firebase le permiten llamar a funciones directamente desde una aplicación de Firebase. Para llamar a una función desde su aplicación de esta manera, escriba e implemente una función HTTPS Callable en Cloud Functions y luego agregue lógica de cliente para llamar a la función desde su aplicación.
Es importante tener en cuenta que las funciones a las que se puede llamar HTTPS son similares pero no idénticas a las funciones HTTP. Para usar las funciones de llamada de HTTPS, debe usar el SDK de cliente para su plataforma junto con la API backend functions.https
(o implementar el protocolo). Los invocables tienen estas diferencias clave con las funciones HTTP:
- Con las llamadas, los tokens de autenticación de Firebase, los tokens de FCM y los tokens de verificación de aplicaciones, cuando están disponibles, se incluyen automáticamente en las solicitudes.
- El activador
functions.https.onCall
deserializa automáticamente el cuerpo de la solicitud y valida los tokens de autenticación.
El SDK de Firebase para Cloud Functions v0.9.1 y versiones posteriores interactúa con estas versiones mínimas del SDK de cliente de Firebase para admitir funciones de HTTPS invocables:
- Firebase SDK para plataformas Apple 10.4.0
- SDK de Firebase para Android 20.2.2
- SDK de JavaScript de Firebase 8.10.1
- Firebase Modular Web SDK versión 9.0
Si desea agregar una funcionalidad similar a una aplicación creada en una plataforma no compatible, consulte la Especificación de protocolo para https.onCall
. El resto de esta guía proporciona instrucciones sobre cómo escribir, implementar y llamar a una función de llamada HTTPS para plataformas Apple, Android, web, C++ y Unity.
Escribir e implementar la función invocable
Utilice functions.https.onCall
para crear una función HTTPS invocable. Este método toma dos parámetros: data
y context
opcional:
// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
// ...
});
Para una función invocable que guarda un mensaje de texto en Realtime Database, por ejemplo, data
podrían contener el texto del mensaje, mientras que los parámetros de context
representan la información de autenticación del usuario:
// Message text passed from the client.
const text = data.text;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;
La distancia entre la ubicación de la función invocable y la ubicación del cliente que llama puede generar latencia en la red. Para optimizar el rendimiento, considere especificar la ubicación de la función cuando corresponda y asegúrese de alinear la ubicación de la llamada con la ubicación establecida cuando inicializa el SDK en el lado del cliente.
Opcionalmente, puede adjuntar una atestación de App Check para ayudar a proteger sus recursos de back-end de abusos, como el fraude de facturación o el phishing. Consulte Habilitar el cumplimiento de App Check para Cloud Functions .
Devolviendo el resultado
Para devolver datos al cliente, devuelva datos que se puedan codificar en JSON. Por ejemplo, para devolver el resultado de una operación de suma:
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: '+',
operationResult: firstNumber + secondNumber,
};
Para devolver datos después de una operación asincrónica, devuelva una promesa. Los datos devueltos por la promesa se devuelven al cliente. Por ejemplo, podría devolver texto desinfectado que la función invocable escribió en Realtime Database:
// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize the message.
return admin.database().ref('/messages').push({
text: sanitizedMessage,
author: { uid, name, picture, email },
}).then(() => {
console.log('New Message written');
// Returning the sanitized message to the client.
return { text: sanitizedMessage };
})
Manejar errores
Para asegurarse de que el cliente obtenga detalles de error útiles, devuelva los errores de un invocable lanzando (o devolviendo una Promesa rechazada con) una instancia de functions.https.HttpsError
. El error tiene un atributo de code
que puede ser uno de los valores enumerados en functions.https.HttpsError
. Los errores también tienen un message
de cadena, que por defecto es una cadena vacía. También pueden tener un campo de details
opcional con un valor arbitrario. Si se arroja un error que no sea HttpsError
desde sus funciones, su cliente recibe un error con el mensaje INTERNAL
y el código internal
.
Por ejemplo, una función podría arrojar errores de autenticación y validación de datos con mensajes de error para volver al cliente que llama:
// Checking attribute.
if (!(typeof text === 'string') || text.length === 0) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
'one arguments "text" containing the message text to add.');
}
// Checking that the user is authenticated.
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
'while authenticated.');
}
Implementar la función invocable
Después de guardar una función invocable completada dentro de index.js
, se implementa junto con todas las demás funciones cuando ejecuta firebase deploy
. Para implementar solo el invocable, use el argumento --only
como se muestra para realizar implementaciones parciales :
firebase deploy --only functions:addMessage
Si encuentra errores de permisos al implementar funciones, asegúrese de que los roles de IAM apropiados estén asignados al usuario que ejecuta los comandos de implementación.
Configurar el entorno de desarrollo de su cliente
Asegúrese de cumplir con todos los requisitos previos, luego agregue las dependencias requeridas y las bibliotecas de clientes a su aplicación.
iOS+
Siga las instrucciones para agregar Firebase a su aplicación de Apple .
Use Swift Package Manager para instalar y administrar las dependencias de Firebase.
- En Xcode, con su proyecto de aplicación abierto, vaya a Archivo > Agregar paquetes .
- Cuando se le solicite, agregue el repositorio del SDK de las plataformas Apple de Firebase:
- Elija la biblioteca de Cloud Functions.
- Cuando termine, Xcode comenzará a resolver y descargar automáticamente sus dependencias en segundo plano.
https://github.com/firebase/firebase-ios-sdk
Web version 9
- Siga las instrucciones para agregar Firebase a su aplicación web . Asegúrese de ejecutar el siguiente comando desde su terminal:
npm install firebase@9.17.0 --save
Requiere manualmente Firebase core y Cloud Functions:
import { initializeApp } from 'firebase/app'; import { getFunctions } from 'firebase/functions'; const app = initializeApp({ projectId: '### CLOUD FUNCTIONS PROJECT ID ###', apiKey: '### FIREBASE API KEY ###', authDomain: '### FIREBASE AUTH DOMAIN ###', }); const functions = getFunctions(app);
Web version 8
- Siga las instrucciones para agregar Firebase a su aplicación web .
- Agregue las bibliotecas cliente de Firebase core y Cloud Functions a su aplicación:
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase.js"></script> <script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-functions.js"></script>
El SDK de Cloud Functions también está disponible como paquete npm.
- Ejecute el siguiente comando desde su terminal:
npm install firebase@8.10.1 --save
- Requerir manualmente el núcleo de Firebase y Cloud Functions:
const firebase = require("firebase"); // Required for side-effects require("firebase/functions");
Kotlin+KTX
Siga las instrucciones para agregar Firebase a su aplicación de Android .
En el archivo Gradle de tu módulo (nivel de aplicación) (generalmente
<project>/<app-module>/build.gradle
), agrega la dependencia para la biblioteca de Android de Cloud Functions. Recomendamos usar Firebase Android BoM para controlar el control de versiones de la biblioteca.dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:31.2.0') // Add the dependency for the Cloud Functions library // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-functions-ktx' }
Al usar Firebase Android BoM , su aplicación siempre usará versiones compatibles de las bibliotecas de Firebase Android.
(Alternativa) Agregar dependencias de la biblioteca de Firebase sin usar el BoM
Si elige no usar Firebase BoM, debe especificar cada versión de la biblioteca de Firebase en su línea de dependencia.
Tenga en cuenta que si usa varias bibliotecas de Firebase en su aplicación, le recomendamos enfáticamente que use la lista de materiales para administrar las versiones de la biblioteca, lo que garantiza que todas las versiones sean compatibles.
dependencies { // Add the dependency for the Cloud Functions library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-functions-ktx:20.2.2' }
Java
Siga las instrucciones para agregar Firebase a su aplicación de Android .
En el archivo Gradle de tu módulo (nivel de aplicación) (generalmente
<project>/<app-module>/build.gradle
), agrega la dependencia para la biblioteca de Android de Cloud Functions. Recomendamos usar Firebase Android BoM para controlar el control de versiones de la biblioteca.dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:31.2.0') // Add the dependency for the Cloud Functions library // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-functions' }
Al usar Firebase Android BoM , su aplicación siempre usará versiones compatibles de las bibliotecas de Firebase Android.
(Alternativa) Agregar dependencias de la biblioteca de Firebase sin usar el BoM
Si elige no usar Firebase BoM, debe especificar cada versión de la biblioteca de Firebase en su línea de dependencia.
Tenga en cuenta que si usa varias bibliotecas de Firebase en su aplicación, le recomendamos enfáticamente que use la lista de materiales para administrar las versiones de la biblioteca, lo que garantiza que todas las versiones sean compatibles.
dependencies { // Add the dependency for the Cloud Functions library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-functions:20.2.2' }
Dart
Siga las instrucciones para agregar Firebase a su aplicación Flutter .
Desde la raíz de su proyecto Flutter, ejecute el siguiente comando para instalar el complemento:
flutter pub add cloud_functions
Una vez completada, reconstruya su aplicación Flutter:
flutter run
Una vez instalado, puede acceder al complemento
cloud_functions
importándolo en su código Dart:import 'package:cloud_functions/cloud_functions.dart';
C++
Para C++ con Android :
- Siga las instrucciones para agregar Firebase a su proyecto de C++ .
- Agregue la biblioteca
firebase_functions
a su archivoCMakeLists.txt
.
Para C++ con plataformas Apple :
- Siga las instrucciones para agregar Firebase a su proyecto de C++ .
- Agregue el pod de Cloud Functions a su
Podfile
:pod 'Firebase/Functions'
- Guarde el archivo, luego ejecute:
pod install
- Agrega el núcleo de Firebase y los marcos de trabajo de Cloud Functions del SDK de Firebase C++ a tu proyecto de Xcode.
-
firebase.framework
-
firebase_functions.framework
-
Unidad
- Siga las instrucciones para agregar Firebase a su proyecto de Unity .
- Agregue el
FirebaseFunctions.unitypackage
del SDK de Firebase Unity a su proyecto de Unity.
Inicializar el SDK del cliente
Inicializa una instancia de Cloud Functions:
Rápido
lazy var functions = Functions.functions()
C objetivo
@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];
Web version 8
firebase.initializeApp({
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
});
// Initialize Cloud Functions through Firebase
var functions = firebase.functions();
Web version 9
const app = initializeApp({
projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
});
const functions = getFunctions(app);
Kotlin+KTX
private lateinit var functions: FirebaseFunctions // ... functions = Firebase.functions
Java
private FirebaseFunctions mFunctions; // ... mFunctions = FirebaseFunctions.getInstance();
Dart
final functions = FirebaseFunctions.instance;
C++
firebase::functions::Functions* functions;
// ...
functions = firebase::functions::Functions::GetInstance(app);
Unidad
functions = Firebase.Functions.DefaultInstance;
Llamar a la función
Rápido
functions.httpsCallable("addMessage").call(["text": inputField.text]) { result, error in
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain {
let code = FunctionsErrorCode(rawValue: error.code)
let message = error.localizedDescription
let details = error.userInfo[FunctionsErrorDetailsKey]
}
// ...
}
if let data = result?.data as? [String: Any], let text = data["text"] as? String {
self.resultField.text = text
}
}
C objetivo
[[_functions HTTPSCallableWithName:@"addMessage"] callWithObject:@{@"text": _inputField.text}
completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
if (error) {
if ([error.domain isEqual:@"com.firebase.functions"]) {
FIRFunctionsErrorCode code = error.code;
NSString *message = error.localizedDescription;
NSObject *details = error.userInfo[@"details"];
}
// ...
}
self->_resultField.text = result.data[@"text"];
}];
Web version 8
var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
var sanitizedMessage = result.data.text;
});
Web version 9
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const sanitizedMessage = data.text;
});
Kotlin+KTX
private fun addMessage(text: String): Task<String> { // Create the arguments to the callable function. val data = hashMapOf( "text" to text, "push" to true ) return functions .getHttpsCallable("addMessage") .call(data) .continueWith { task -> // This continuation runs on either success or failure, but if the task // has failed then result will throw an Exception which will be // propagated down. val result = task.result?.data as String result } }
Java
private Task<String> addMessage(String text) { // Create the arguments to the callable function. Map<String, Object> data = new HashMap<>(); data.put("text", text); data.put("push", true); return mFunctions .getHttpsCallable("addMessage") .call(data) .continueWith(new Continuation<HttpsCallableResult, String>() { @Override public String then(@NonNull Task<HttpsCallableResult> task) throws Exception { // This continuation runs on either success or failure, but if the task // has failed then getResult() will throw an Exception which will be // propagated down. String result = (String) task.getResult().getData(); return result; } }); }
Dart
final result =
await FirebaseFunctions.instance.httpsCallable('addMessage').call();
C++
firebase::Future<firebase::functions::HttpsCallableResult> AddMessage(
const std::string& text) {
// Create the arguments to the callable function.
firebase::Variant data = firebase::Variant::EmptyMap();
data.map()["text"] = firebase::Variant(text);
data.map()["push"] = true;
// Call the function and add a callback for the result.
firebase::functions::HttpsCallableReference doSomething =
functions->GetHttpsCallable("addMessage");
return doSomething.Call(data);
}
Unidad
private Task<string> addMessage(string text) {
// Create the arguments to the callable function.
var data = new Dictionary<string, object>();
data["text"] = text;
data["push"] = true;
// Call the function and extract the operation from the result.
var function = functions.GetHttpsCallable("addMessage");
return function.CallAsync(data).ContinueWith((task) => {
return (string) task.Result.Data;
});
}
Manejar errores en el cliente
El cliente recibe un error si el servidor arrojó un error o si la promesa resultante fue rechazada.
Si el error devuelto por la función es del tipo function.https.HttpsError
, el cliente recibe el code
de error, el message
y los details
del error del servidor. De lo contrario, el error contiene el mensaje INTERNAL
y el código INTERNAL
. Consulte la guía sobre cómo manejar los errores en su función invocable.
Rápido
if let error = error as NSError? {
if error.domain == FunctionsErrorDomain {
let code = FunctionsErrorCode(rawValue: error.code)
let message = error.localizedDescription
let details = error.userInfo[FunctionsErrorDetailsKey]
}
// ...
}
C objetivo
if (error) {
if ([error.domain isEqual:@"com.firebase.functions"]) {
FIRFunctionsErrorCode code = error.code;
NSString *message = error.localizedDescription;
NSObject *details = error.userInfo[@"details"];
}
// ...
}
Web version 8
var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
var sanitizedMessage = result.data.text;
})
.catch((error) => {
// Getting the Error details.
var code = error.code;
var message = error.message;
var details = error.details;
// ...
});
Web version 9
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const sanitizedMessage = data.text;
})
.catch((error) => {
// Getting the Error details.
const code = error.code;
const message = error.message;
const details = error.details;
// ...
});
Kotlin+KTX
addMessage(inputMessage) .addOnCompleteListener { task -> if (!task.isSuccessful) { val e = task.exception if (e is FirebaseFunctionsException) { val code = e.code val details = e.details } } }
Java
addMessage(inputMessage) .addOnCompleteListener(new OnCompleteListener<String>() { @Override public void onComplete(@NonNull Task<String> task) { if (!task.isSuccessful()) { Exception e = task.getException(); if (e instanceof FirebaseFunctionsException) { FirebaseFunctionsException ffe = (FirebaseFunctionsException) e; FirebaseFunctionsException.Code code = ffe.getCode(); Object details = ffe.getDetails(); } } } });
Dart
try {
final result =
await FirebaseFunctions.instance.httpsCallable('addMessage').call();
} on FirebaseFunctionsException catch (error) {
print(error.code);
print(error.details);
print(error.message);
}
C++
void OnAddMessageCallback(
const firebase::Future<firebase::functions::HttpsCallableResult>& future) {
if (future.error() != firebase::functions::kErrorNone) {
// Function error code, will be kErrorInternal if the failure was not
// handled properly in the function call.
auto code = static_cast<firebase::functions::Error>(future.error());
// Display the error in the UI.
DisplayError(code, future.error_message());
return;
}
const firebase::functions::HttpsCallableResult* result = future.result();
firebase::Variant data = result->data();
// This will assert if the result returned from the function wasn't a string.
std::string message = data.string_value();
// Display the result in the UI.
DisplayResult(message);
}
// ...
// ...
auto future = AddMessage(message);
future.OnCompletion(OnAddMessageCallback);
// ...
Unidad
addMessage(text).ContinueWith((task) => {
if (task.IsFaulted) {
foreach (var inner in task.Exception.InnerExceptions) {
if (inner is FunctionsException) {
var e = (FunctionsException) inner;
// Function error code, will be INTERNAL if the failure
// was not handled properly in the function call.
var code = e.ErrorCode;
var message = e.ErrorMessage;
}
}
} else {
string result = task.Result;
}
});
Recomendado: Evite el abuso con App Check
Antes de iniciar su aplicación, debe habilitar App Check para ayudar a garantizar que solo sus aplicaciones puedan acceder a sus puntos finales de función invocables.