获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

Llama a funciones desde tu app

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.2.0
  • SDK de Firebase para Android 20.2.1
  • 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 donde 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.

  1. En Xcode, con su proyecto de aplicación abierto, vaya a Archivo > Agregar paquetes .
  2. Cuando se le solicite, agregue el repositorio del SDK de las plataformas Apple de Firebase:
  3.   https://github.com/firebase/firebase-ios-sdk
  4. Elija la biblioteca de Cloud Functions.
  5. Cuando termine, Xcode comenzará a resolver y descargar automáticamente sus dependencias en segundo plano.

Web version 9

  1. 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.14.0 --save
    
  2. 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

  1. Siga las instrucciones para agregar Firebase a su aplicación web .
  2. 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.

  1. Ejecute el siguiente comando desde su terminal:
    npm install firebase@8.10.1 --save
    
  2. Requerir manualmente el núcleo de Firebase y Cloud Functions:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Java

  1. Siga las instrucciones para agregar Firebase a su aplicación de Android .

  2. 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.1.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.1'
    }
    

Kotlin+KTX

  1. Siga las instrucciones para agregar Firebase a su aplicación de Android .

  2. 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.1.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.1'
    }
    

Dart

  1. Siga las instrucciones para agregar Firebase a su aplicación Flutter .

  2. Desde la raíz de su proyecto Flutter, ejecute el siguiente comando para instalar el complemento:

    flutter pub add cloud_functions
    
  3. Una vez completada, reconstruya su aplicación Flutter:

    flutter run
    
  4. 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 :

  1. Siga las instrucciones para agregar Firebase a su proyecto de C++ .
  2. Agregue la biblioteca firebase_functions a su archivo CMakeLists.txt .

Para C++ con plataformas Apple :

  1. Siga las instrucciones para agregar Firebase a su proyecto de C++ .
  2. Agregue el pod de Cloud Functions a su Podfile :
    pod 'Firebase/Functions'
  3. Guarde el archivo, luego ejecute:
    pod install
  4. 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

  1. Siga las instrucciones para agregar Firebase a su proyecto de Unity .
  2. 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);

Java

private FirebaseFunctions mFunctions;
// ...
mFunctions = FirebaseFunctions.getInstance();

Kotlin+KTX

private lateinit var functions: FirebaseFunctions
// ...
functions = Firebase.functions

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;
  });

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;
                }
            });
}

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
        }
}

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;
    // ...
  });

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();
                    }
                }
            }
        });

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
            }
        }
    }

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;
  }
});

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.