Los SDK de cliente de Cloud Functions para Firebase te permiten llamar funciones directamente desde una aplicación de Firebase. Para llamar una función desde su aplicación de esta manera, escriba e implemente una función HTTP invocable en Cloud Functions y luego agregue lógica de cliente para llamar la función desde su aplicación.
Es importante tener en cuenta que las funciones invocables HTTP son similares pero no idénticas a las funciones HTTP. Para utilizar funciones invocables HTTP, debe utilizar el SDK del cliente para su plataforma junto con la API de backend (o implementar el protocolo). Los callables tienen estas diferencias clave con las funciones HTTP:
- Con los callables, los tokens de Firebase Authentication, los tokens de FCM y los tokens de App Check, cuando están disponibles, se incluyen automáticamente en las solicitudes.
- El desencadenador deserializa automáticamente el cuerpo de la solicitud y valida los tokens de autenticación.
El SDK de Firebase para Cloud Functions de segunda generación y superiores interopera con estas versiones mínimas del SDK de cliente de Firebase para admitir funciones invocables HTTPS:
- SDK de Firebase para plataformas Apple 10.19.0
- SDK de Firebase para Android 20.4.0
- SDK web modular de Firebase versión 9.7.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 invocable HTTP para plataformas Apple, Android, web, C++ y Unity.
Escribir e implementar la función invocable
Los ejemplos de código de esta sección se basan en un ejemplo de inicio rápido completo que demuestra cómo enviar solicitudes a una función del lado del servidor y obtener una respuesta utilizando uno de los SDK del cliente. Para comenzar, importe los módulos necesarios:
Nodo.js
// Dependencies for callable functions.
const {onCall, HttpsError} = require("firebase-functions/v2/https");
const {logger} = require("firebase-functions/v2");
// Dependencies for the addMessage function.
const {getDatabase} = require("firebase-admin/database");
const sanitizer = require("./sanitizer");
Pitón
# Dependencies for callable functions.
from firebase_functions import https_fn, options
# Dependencies for writing to Realtime Database.
from firebase_admin import db, initialize_app
Utilice el controlador de solicitudes para su plataforma ( functions.https.onCall
) o on_call
) para crear una función invocable HTTPS. Este método toma un parámetro de solicitud:
Nodo.js
// Saves a message to the Firebase Realtime Database but sanitizes the
// text by removing swearwords.
exports.addmessage = onCall((request) => {
// ...
});
Pitón
@https_fn.on_call()
def addmessage(req: https_fn.CallableRequest) -> Any:
"""Saves a message to the Firebase Realtime Database but sanitizes the text
by removing swear words."""
El parámetro request
contiene datos pasados desde la aplicación cliente, así como contexto adicional como el estado de autenticación. Para una función invocable que guarda un mensaje de texto en Realtime Database, por ejemplo, data
podrían contener el texto del mensaje, junto con la información de autenticación en auth
:
Nodo.js
// Message text passed from the client.
const text = request.data.text;
// Authentication / user information is automatically added to the request.
const uid = request.auth.uid;
const name = request.auth.token.name || null;
const picture = request.auth.token.picture || null;
const email = request.auth.token.email || null;
Pitón
# Message text passed from the client.
text = req.data["text"]
# Authentication / user information is automatically added to the request.
uid = req.auth.uid
name = req.auth.token.get("name", "")
picture = req.auth.token.get("picture", "")
email = req.auth.token.get("email", "")
La distancia entre la ubicación de la función invocable y la ubicación del cliente que llama puede crear 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 del invocable con la ubicación establecida cuando inicializa el SDK en el lado del cliente.
Opcionalmente, puede adjuntar una certificación de App Check para ayudar a proteger sus recursos de backend contra abusos, como fraude de facturación o phishing. Consulte Habilitar la aplicación de App Check para funciones en la nube .
Devolviendo el resultado
Para enviar datos al cliente, devuelva datos que puedan codificarse en JSON. Por ejemplo, para devolver el resultado de una operación de suma:
Nodo.js
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: "+",
operationResult: firstNumber + secondNumber,
};
Pitón
return {
"firstNumber": first_number,
"secondNumber": second_number,
"operator": "+",
"operationResult": first_number + second_number
}
El texto desinfectado del ejemplo de texto del mensaje se devuelve tanto al cliente como a Realtime Database. En Node.js, esto se puede hacer de forma asincrónica mediante una promesa de JavaScript:
Nodo.js
// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize message.
return getDatabase().ref("/messages").push({
text: sanitizedMessage,
author: {uid, name, picture, email},
}).then(() => {
logger.info("New Message written");
// Returning the sanitized message to the client.
return {text: sanitizedMessage};
})
Pitón
# Saving the new message to the Realtime Database.
sanitized_message = sanitize_text(text) # Sanitize message.
db.reference("/messages").push({ # type: ignore
"text": sanitized_message,
"author": {
"uid": uid,
"name": name,
"picture": picture,
"email": email
}
})
print("New message written")
# Returning the sanitized message to the client.
return {"text": sanitized_message}
Configurar CORS (intercambio de recursos entre orígenes)
Utilice la opción cors
para controlar qué orígenes pueden acceder a su función.
De forma predeterminada, las funciones invocables tienen CORS configurado para permitir solicitudes de todos los orígenes. Para permitir algunas solicitudes de orígenes cruzados, pero no todas, pase una lista de dominios específicos o expresiones regulares que deberían permitirse. Por ejemplo:
Nodo.js
const { onCall } = require("firebase-functions/v2/https");
exports.getGreeting = onCall(
{ cors: [/firebase\.com$/, "flutter.com"] },
(request) => {
return "Hello, world!";
}
);
Para prohibir solicitudes de origen cruzado, establezca la política cors
en false
.
Manejar errores
Para garantizar que el cliente obtenga detalles útiles del error, devuelva errores de un invocable lanzando (o para Node.js devolviendo una Promesa rechazada con) una instancia de functions.https.HttpsError
o https_fn.HttpsError
. El error tiene un atributo code
que puede ser uno de los valores enumerados en Códigos de estado de gRPC. Los errores también tienen una cadena message
, que por defecto es una cadena vacía. También pueden tener un campo details
opcional con un valor arbitrario. Si sus funciones arrojan un error que no sea un error HTTPS, su cliente recibe un error con el mensaje INTERNAL
y el código internal
.
Por ejemplo, una función podría generar errores de validación y autenticación de datos con mensajes de error para devolver al cliente que llama:
Nodo.js
// Checking attribute.
if (!(typeof text === "string") || text.length === 0) {
// Throwing an HttpsError so that the client gets the error details.
throw new 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 (!request.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new HttpsError("failed-precondition", "The function must be " +
"called while authenticated.");
}
Pitón
# Checking attribute.
if not isinstance(text, str) or len(text) < 1:
# Throwing an HttpsError so that the client gets the error details.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message=('The function must be called with one argument, "text",'
" containing the message text to add."))
# Checking that the user is authenticated.
if req.auth is None:
# Throwing an HttpsError so that the client gets the error details.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.FAILED_PRECONDITION,
message="The function must be called while authenticated.")
Implementar la función invocable
Después de guardar una función invocable completa dentro de index.js
, se implementa junto con todas las demás funciones cuando ejecuta firebase deploy
. Para implementar solo lo 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 se asignen las funciones de IAM adecuadas al usuario que ejecuta los comandos de implementación.
Configure el entorno de desarrollo de su cliente
Asegúrese de cumplir con los requisitos previos y luego agregue las dependencias y bibliotecas cliente requeridas a su aplicación.
iOS+
Sigue las instrucciones para agregar Firebase a tu aplicación de Apple .
Utilice Swift Package Manager para instalar y administrar las dependencias de Firebase.
- En Xcode, con el proyecto de su aplicación abierto, navegue hasta Archivo > Agregar paquetes .
- Cuando se le solicite, agregue el repositorio SDK de las plataformas Firebase Apple:
- Elija la biblioteca de Cloud Functions.
- Agregue el indicador
-ObjC
a la sección Otros indicadores del vinculador de la configuración de compilación de su objetivo. - Cuando termine, Xcode comenzará automáticamente a resolver y descargar sus dependencias en segundo plano.
https://github.com/firebase/firebase-ios-sdk.git
API modular web
- Siga las instrucciones para agregar Firebase a su aplicación web . Asegúrese de ejecutar el siguiente comando desde su terminal:
npm install firebase@10.7.1 --save
Requiere manualmente tanto Firebase core como 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);
Androide
Siga las instrucciones para agregar Firebase a su aplicación de Android .
En el archivo Gradle de su módulo (nivel de aplicación) (generalmente
<project>/<app-module>/build.gradle.kts
o<project>/<app-module>/build.gradle
), agregue la dependencia para Cloud Functions biblioteca para Android. Recomendamos utilizar 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:32.7.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.
¿Busca un módulo de biblioteca específico de Kotlin? A partir de octubre de 2023 (Firebase BoM 32.5.0) , tanto los desarrolladores de Kotlin como los de Java podrán depender del módulo de biblioteca principal (para más detalles, consulte las preguntas frecuentes sobre esta iniciativa ).(Alternativa) Agregue dependencias de la biblioteca de Firebase sin usar la BoM
Si elige no utilizar la BoM de Firebase, 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 encarecidamente usar la BoM 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.4.0") }
Inicializar el SDK del cliente
Inicialice una instancia de Cloud Functions:
Rápido
lazy var functions = Functions.functions()
C objetivo
@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];
API modular web
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();
Llame 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"];
}];
API con espacio de nombres web
var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
var sanitizedMessage = result.data.text;
});
API modular web
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(
{
"text": text,
"push": true,
},
);
_response = result.data as String;
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 de tipo function.https.HttpsError
, entonces el cliente recibe el code
de error, message
y 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 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"];
}
// ...
}
API con espacio de nombres web
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;
// ...
});
API modular web
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 funciones invocables.
,Los SDK de cliente de Cloud Functions para Firebase te permiten llamar funciones directamente desde una aplicación de Firebase. Para llamar una función desde su aplicación de esta manera, escriba e implemente una función HTTP invocable en Cloud Functions y luego agregue lógica de cliente para llamar la función desde su aplicación.
Es importante tener en cuenta que las funciones invocables HTTP son similares pero no idénticas a las funciones HTTP. Para utilizar funciones invocables HTTP, debe utilizar el SDK del cliente para su plataforma junto con la API de backend (o implementar el protocolo). Los callables tienen estas diferencias clave con las funciones HTTP:
- Con los callables, los tokens de Firebase Authentication, los tokens de FCM y los tokens de App Check, cuando están disponibles, se incluyen automáticamente en las solicitudes.
- El desencadenador deserializa automáticamente el cuerpo de la solicitud y valida los tokens de autenticación.
El SDK de Firebase para Cloud Functions de segunda generación y superiores interopera con estas versiones mínimas del SDK de cliente de Firebase para admitir funciones invocables HTTPS:
- SDK de Firebase para plataformas Apple 10.19.0
- SDK de Firebase para Android 20.4.0
- SDK web modular de Firebase versión 9.7.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 invocable HTTP para plataformas Apple, Android, web, C++ y Unity.
Escribir e implementar la función invocable
Los ejemplos de código de esta sección se basan en un ejemplo de inicio rápido completo que demuestra cómo enviar solicitudes a una función del lado del servidor y obtener una respuesta utilizando uno de los SDK del cliente. Para comenzar, importe los módulos necesarios:
Nodo.js
// Dependencies for callable functions.
const {onCall, HttpsError} = require("firebase-functions/v2/https");
const {logger} = require("firebase-functions/v2");
// Dependencies for the addMessage function.
const {getDatabase} = require("firebase-admin/database");
const sanitizer = require("./sanitizer");
Pitón
# Dependencies for callable functions.
from firebase_functions import https_fn, options
# Dependencies for writing to Realtime Database.
from firebase_admin import db, initialize_app
Utilice el controlador de solicitudes para su plataforma ( functions.https.onCall
) o on_call
) para crear una función invocable HTTPS. Este método toma un parámetro de solicitud:
Nodo.js
// Saves a message to the Firebase Realtime Database but sanitizes the
// text by removing swearwords.
exports.addmessage = onCall((request) => {
// ...
});
Pitón
@https_fn.on_call()
def addmessage(req: https_fn.CallableRequest) -> Any:
"""Saves a message to the Firebase Realtime Database but sanitizes the text
by removing swear words."""
El parámetro request
contiene datos pasados desde la aplicación cliente, así como contexto adicional como el estado de autenticación. Para una función invocable que guarda un mensaje de texto en Realtime Database, por ejemplo, data
podrían contener el texto del mensaje, junto con la información de autenticación en auth
:
Nodo.js
// Message text passed from the client.
const text = request.data.text;
// Authentication / user information is automatically added to the request.
const uid = request.auth.uid;
const name = request.auth.token.name || null;
const picture = request.auth.token.picture || null;
const email = request.auth.token.email || null;
Pitón
# Message text passed from the client.
text = req.data["text"]
# Authentication / user information is automatically added to the request.
uid = req.auth.uid
name = req.auth.token.get("name", "")
picture = req.auth.token.get("picture", "")
email = req.auth.token.get("email", "")
La distancia entre la ubicación de la función invocable y la ubicación del cliente que llama puede crear 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 del invocable con la ubicación establecida cuando inicializa el SDK en el lado del cliente.
Opcionalmente, puede adjuntar una certificación de App Check para ayudar a proteger sus recursos de backend contra abusos, como fraude de facturación o phishing. Consulte Habilitar la aplicación de App Check para funciones en la nube .
Devolviendo el resultado
Para enviar datos al cliente, devuelva datos que puedan codificarse en JSON. Por ejemplo, para devolver el resultado de una operación de suma:
Nodo.js
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: "+",
operationResult: firstNumber + secondNumber,
};
Pitón
return {
"firstNumber": first_number,
"secondNumber": second_number,
"operator": "+",
"operationResult": first_number + second_number
}
El texto desinfectado del ejemplo de texto del mensaje se devuelve tanto al cliente como a Realtime Database. En Node.js, esto se puede hacer de forma asincrónica mediante una promesa de JavaScript:
Nodo.js
// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize message.
return getDatabase().ref("/messages").push({
text: sanitizedMessage,
author: {uid, name, picture, email},
}).then(() => {
logger.info("New Message written");
// Returning the sanitized message to the client.
return {text: sanitizedMessage};
})
Pitón
# Saving the new message to the Realtime Database.
sanitized_message = sanitize_text(text) # Sanitize message.
db.reference("/messages").push({ # type: ignore
"text": sanitized_message,
"author": {
"uid": uid,
"name": name,
"picture": picture,
"email": email
}
})
print("New message written")
# Returning the sanitized message to the client.
return {"text": sanitized_message}
Configurar CORS (intercambio de recursos entre orígenes)
Utilice la opción cors
para controlar qué orígenes pueden acceder a su función.
De forma predeterminada, las funciones invocables tienen CORS configurado para permitir solicitudes de todos los orígenes. Para permitir algunas solicitudes de orígenes cruzados, pero no todas, pase una lista de dominios específicos o expresiones regulares que deberían permitirse. Por ejemplo:
Nodo.js
const { onCall } = require("firebase-functions/v2/https");
exports.getGreeting = onCall(
{ cors: [/firebase\.com$/, "flutter.com"] },
(request) => {
return "Hello, world!";
}
);
Para prohibir solicitudes de origen cruzado, establezca la política cors
en false
.
Manejar errores
Para garantizar que el cliente obtenga detalles útiles del error, devuelva errores de un invocable lanzando (o para Node.js devolviendo una Promesa rechazada con) una instancia de functions.https.HttpsError
o https_fn.HttpsError
. El error tiene un atributo code
que puede ser uno de los valores enumerados en Códigos de estado de gRPC. Los errores también tienen una cadena message
, que por defecto es una cadena vacía. También pueden tener un campo details
opcional con un valor arbitrario. Si sus funciones arrojan un error que no sea un error HTTPS, su cliente recibe un error con el mensaje INTERNAL
y el código internal
.
Por ejemplo, una función podría generar errores de validación y autenticación de datos con mensajes de error para devolver al cliente que llama:
Nodo.js
// Checking attribute.
if (!(typeof text === "string") || text.length === 0) {
// Throwing an HttpsError so that the client gets the error details.
throw new 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 (!request.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new HttpsError("failed-precondition", "The function must be " +
"called while authenticated.");
}
Pitón
# Checking attribute.
if not isinstance(text, str) or len(text) < 1:
# Throwing an HttpsError so that the client gets the error details.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.INVALID_ARGUMENT,
message=('The function must be called with one argument, "text",'
" containing the message text to add."))
# Checking that the user is authenticated.
if req.auth is None:
# Throwing an HttpsError so that the client gets the error details.
raise https_fn.HttpsError(code=https_fn.FunctionsErrorCode.FAILED_PRECONDITION,
message="The function must be called while authenticated.")
Implementar la función invocable
Después de guardar una función invocable completa dentro de index.js
, se implementa junto con todas las demás funciones cuando ejecuta firebase deploy
. Para implementar solo lo 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 se asignen las funciones de IAM adecuadas al usuario que ejecuta los comandos de implementación.
Configure el entorno de desarrollo de su cliente
Asegúrese de cumplir con los requisitos previos y luego agregue las dependencias y bibliotecas cliente requeridas a su aplicación.
iOS+
Sigue las instrucciones para agregar Firebase a tu aplicación de Apple .
Utilice Swift Package Manager para instalar y administrar las dependencias de Firebase.
- En Xcode, con el proyecto de su aplicación abierto, navegue hasta Archivo > Agregar paquetes .
- Cuando se le solicite, agregue el repositorio SDK de las plataformas Firebase Apple:
- Elija la biblioteca de Cloud Functions.
- Agregue el indicador
-ObjC
a la sección Otros indicadores del vinculador de la configuración de compilación de su objetivo. - Cuando termine, Xcode comenzará automáticamente a resolver y descargar sus dependencias en segundo plano.
https://github.com/firebase/firebase-ios-sdk.git
API modular web
- Siga las instrucciones para agregar Firebase a su aplicación web . Asegúrese de ejecutar el siguiente comando desde su terminal:
npm install firebase@10.7.1 --save
Requiere manualmente tanto Firebase core como 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);
Androide
Siga las instrucciones para agregar Firebase a su aplicación de Android .
En el archivo Gradle de su módulo (nivel de aplicación) (generalmente
<project>/<app-module>/build.gradle.kts
o<project>/<app-module>/build.gradle
), agregue la dependencia para Cloud Functions biblioteca para Android. Recomendamos utilizar 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:32.7.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.
¿Busca un módulo de biblioteca específico de Kotlin? A partir de octubre de 2023 (Firebase BoM 32.5.0) , tanto los desarrolladores de Kotlin como los de Java podrán depender del módulo de biblioteca principal (para más detalles, consulte las preguntas frecuentes sobre esta iniciativa ).(Alternativa) Agregue dependencias de la biblioteca de Firebase sin usar la BoM
Si elige no utilizar la BoM de Firebase, 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 encarecidamente usar la BoM 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.4.0") }
Inicializar el SDK del cliente
Inicialice una instancia de Cloud Functions:
Rápido
lazy var functions = Functions.functions()
C objetivo
@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];
API modular web
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();
Llame 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"];
}];
API con espacio de nombres web
var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
var sanitizedMessage = result.data.text;
});
API modular web
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(
{
"text": text,
"push": true,
},
);
_response = result.data as String;
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 de tipo function.https.HttpsError
, entonces el cliente recibe el code
de error, message
y 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 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"];
}
// ...
}
API con espacio de nombres web
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;
// ...
});
API modular web
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 funciones invocables.