Catch up on everthing we announced at this year's Firebase Summit. Learn more

Вызов функций из вашего приложения

Облачные функции для клиентских SDK Firebase позволяют вызывать функции непосредственно из приложения Firebase. Чтобы вызвать функцию из вашего приложения таким образом, напишите и разверните функцию HTTPS Callable в облачных функциях, а затем добавьте клиентскую логику для вызова функции из вашего приложения.

Это важно иметь в виду , что HTTPS Вызываемые функции аналогичные , но не идентичные HTTP функции. Для того, чтобы использовать HTTPS вызываемые функции , которые вы должны использовать клиент SDK для вашей платформы вместе с functions.https BACKEND API (или реализации протокола). Вызываемые объекты имеют следующие ключевые отличия от функций HTTP:

  • С вызываемыми объектами токены аутентификации Firebase, токены FCM и токены проверки приложений, если они доступны, автоматически включаются в запросы.
  • functions.https.onCall триггер автоматически десериализует тело запроса и проверяет AUTH маркеров.

Firebase SDK для облачных функций v0.9.1 и выше взаимодействует с этими минимальными версиями клиентского SDK Firebase для поддержки вызываемых функций HTTPS:

  • Firebase SDK для платформ Apple 8.10.0
  • Firebase SDK для Android 20.0.1
  • SDK Firebase для JavaScript 8.10.0
  • Модульный веб-SDK Firebase версии 9.0

Если вы хотите добавить аналогичные функциональные возможности приложения , построенного на платформе неподдерживаемых см Спецификация протокола для https.onCall . Остальная часть этого руководства содержит инструкции по написанию, развертыванию и вызову вызываемой функции HTTPS для платформ Apple, Android, Интернета, C ++ и Unity.

Напишите и разверните вызываемую функцию

Использование functions.https.onCall для создания HTTPS вызываемой функции. Этот метод принимает два параметра: data и дополнительный context :

// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
  // ...
});

Для вызываемой функции , которая позволяет экономить текстовое сообщение в базу данных в реальное время, например, data может содержать текст сообщения, в то время как context параметры представляют информацию аутентификации пользователя:

// 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;

Расстояние между местоположением вызываемой функции и местоположением вызывающего клиента может создавать задержку в сети. Для оптимальной производительности, рассмотрите возможность задания функции местоположения , когда это применимо, и убедитесь в том , чтобы выровнять расположение отзывной с набором местоположения при инициализации SDK на стороне клиента.

При желании вы можете прикрепить подтверждение проверки приложений, чтобы защитить свои внутренние ресурсы от злоупотреблений, таких как мошенничество с выставлением счетов или фишинг. См Включить App Проверка соблюдения для облачных функций .

Отправка результата

Чтобы отправить данные обратно клиенту, верните данные, которые можно закодировать в формате JSON. Например, чтобы вернуть результат операции сложения:

// returning result.
return {
  firstNumber: firstNumber,
  secondNumber: secondNumber,
  operator: '+',
  operationResult: firstNumber + secondNumber,
};

Чтобы вернуть данные после асинхронной операции, верните обещание. Данные, возвращаемые обещанием, отправляются обратно клиенту. Например, вы можете вернуть очищенный текст, который вызываемая функция записала в базу данных реального времени:

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

Обработка ошибок

Для того, чтобы убедиться , что клиент получает полезные сведения об ошибках, ошибки возвращаемых из вызываемых бросая (или возвращая Promise отвергается) экземпляр functions.https.HttpsError . Ошибка имеет code атрибут , который может быть одним из значений , перечисленных в functions.https.HttpsError . Ошибки также струнное message , который по умолчанию пустой строки. Они также могут иметь опциональные details поля с произвольным значением. Если другая ошибка , чем HttpsError выбрасываются из ваших функций, ваш клиент вместо получает сообщение об ошибке с сообщением INTERNAL и кодом internal .

Например, функция может выдавать ошибки проверки данных и аутентификации с сообщениями об ошибках для возврата вызывающему клиенту:

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

Разверните вызываемую функцию

После того, как вы сохраните заполненную вызываемую функцию в index.js , она развертывается вместе со всеми другими функциями , когда вы запускаете firebase deploy . Для того, чтобы развернуть только вызываемые, использовать --only аргумента , как показано , чтобы выполнить частичные развертывает :

$ firebase deploy --only functions:addMessage

Если вы столкнулись с разрешениями ошибок при развертывании функции, убедитесь , что соответствующие роли IAM назначаются пользователем , запустившим команды развертывания.

Настройте свою клиентскую среду разработки

Убедитесь, что вы выполняете все предварительные требования, а затем добавьте в приложение необходимые зависимости и клиентские библиотеки.

iOS +

Следуйте инструкциям , чтобы добавить Firebase в приложение Apple , .

Используйте Swift Package Manager для установки и управления зависимостями Firebase.

  1. В Xcode, с приложением проекта открыто, перейдите в меню Файл> Swift пакеты> Добавить пакет Завис.
  2. При появлении запроса добавьте репозиторий Firebase Apple Platform SDK:
  3.   https://github.com/firebase/firebase-ios-sdk
      
  4. Выберите библиотеку Cloud Functions.
  5. По завершении Xcode автоматически начнет разрешение и загрузку ваших зависимостей в фоновом режиме.

Веб-версия 9

  1. Следуйте инструкциям , чтобы добавить Firebase к вашему веб - приложение . Убедитесь в том , чтобы выполнить следующую команду из вашего терминала:
    npm install firebase@9.6.0 --save
    
  2. Вручную требовать как ядро ​​Firebase, так и облачные функции:

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

Веб-версия 8

  1. Следуйте инструкциям , чтобы добавить Firebase к вашему веб - приложение .
  2. Добавить ядро Firebase и облачные функции библиотеки клиента для вашего приложения:
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-functions.js"></script>
    

SDK Cloud Functions также доступен в виде пакета npm.

  1. Выполните следующую команду из вашего терминала:
    npm install firebase@8.10.0 --save
    
  2. Вручную требуют как ядра Firebase и облачных функций:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Джава

  1. Следуйте инструкции , чтобы добавить Firebase в свой Android приложения .

  2. Использование Firebase Android Банка Москвы , объявить зависимость для облачных функций библиотеки Android в вашем модуле (приложение уровня) Gradle файл (обычно app/build.gradle ).

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:29.0.1')
    
        // Declare 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'
    }
    

    С помощью Firebase Android Банка Москвы , ваше приложение будет всегда использовать совместимые версии библиотек Firebase Android.

    (Альтернативный) Объявляет Firebase библиотеки зависимостей без использования спецификации

    Если вы решите не использовать Firebase BoM, вы должны указать каждую версию библиотеки Firebase в ее строке зависимости.

    Обратите внимание , что если вы используете несколько библиотеки Firebase в вашем приложении, мы настоятельно рекомендуем использовать спецификации для управления версиями библиотеки, что гарантирует , что все версии совместимы.

    dependencies {
        // Declare 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.0.1'
    }
    

Котлин + KTX

  1. Следуйте инструкции , чтобы добавить Firebase в свой Android приложения .

  2. Использование Firebase Android Банка Москвы , объявить зависимость для облачных функций библиотеки Android в вашем модуле (приложение уровня) Gradle файл (обычно app/build.gradle ).

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:29.0.1')
    
        // Declare 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'
    }
    

    С помощью Firebase Android Банка Москвы , ваше приложение будет всегда использовать совместимые версии библиотек Firebase Android.

    (Альтернативный) Объявляет Firebase библиотеки зависимостей без использования спецификации

    Если вы решите не использовать Firebase BoM, вы должны указать каждую версию библиотеки Firebase в ее строке зависимости.

    Обратите внимание , что если вы используете несколько библиотеки Firebase в вашем приложении, мы настоятельно рекомендуем использовать спецификации для управления версиями библиотеки, что гарантирует , что все версии совместимы.

    dependencies {
        // Declare 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.0.1'
    }
    

C ++

Для C ++ с Android:

  1. Следуйте инструкциям , чтобы добавить Firebase в свой проект C ++ .
  2. Добавьте firebase_functions библиотеку в свой CMakeLists.txt файл.

Для C ++ с Apple , платформ:

  1. Следуйте инструкциям , чтобы добавить Firebase в свой проект C ++ .
  2. Добавьте облако Функции стручок к вашему Podfile :
    pod 'Firebase/Functions'
  3. Сохранить файл, а затем запустить:
    pod install
  4. Добавить ядро Firebase и облачные структуры функций из ++ SDK Firebase C для вашего проекта Xcode.
    • firebase.framework
    • firebase_functions.framework

Единство

  1. Следуйте инструкциям , чтобы добавить Firebase в свой проект Unity .
  2. Добавьте FirebaseFunctions.unitypackage от Unity SDK Firebase для вашего проекта Unity.

Инициализировать клиентский SDK

Инициализируйте экземпляр облачных функций:

Быстрый

lazy var functions = Functions.functions()

Цель-C

@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];

Веб-версия 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();

Веб-версия 9

const app = initializeApp({
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
});
const functions = getFunctions(app);

Джава

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

Котлин + KTX

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

C ++

firebase::functions::Functions* functions;
// ...
functions = firebase::functions::Functions::GetInstance(app);

Единство

functions = Firebase.Functions.DefaultInstance;

Вызов функции

Быстрый

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

[[_functions HTTPSCallableWithName:@"addMessage"] callWithObject:@{@"text": _inputField.text}
                                                      completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
  if (error) {
    if (error.domain == FIRFunctionsErrorDomain) {
      FIRFunctionsErrorCode code = error.code;
      NSString *message = error.localizedDescription;
      NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
    }
    // ...
  }
  self->_resultField.text = result.data[@"text"];
}];

Веб-версия 8

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
  });

Веб-версия 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;
  });

Джава

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

Котлин + 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
            }
}

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

Единство

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

Обработка ошибок на клиенте

Клиент получает сообщение об ошибке, если сервер выдал ошибку или полученное обещание было отклонено.

Если ошибка , возвращаемая функция имеет типа function.https.HttpsError , то клиент получает ошибку code , message , и details от ошибки сервера. В противном случае ошибка содержит сообщение INTERNAL и код INTERNAL . См рекомендации для того, как обрабатывать ошибки в вашей вызываемую функцию.

Быстрый

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

if (error) {
  if (error.domain == FIRFunctionsErrorDomain) {
    FIRFunctionsErrorCode code = error.code;
    NSString *message = error.localizedDescription;
    NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
  }
  // ...
}

Веб-версия 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;
    // ...
  });

Веб-версия 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;
    // ...
  });

Джава

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

                    // ...
                }

                // ...
            }
        });

Котлин + KTX

addMessage(inputMessage)
        .addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                val e = task.exception
                if (e is FirebaseFunctionsException) {
                    val code = e.code
                    val details = e.details
                }

                // ...
            }

            // ...
        })

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

Единство

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

Перед тем как запустить приложение, вы должны позволить App Check , чтобы помочь гарантировать , что только ваши приложения могут получить доступ к функции вызываемых конечным точкам.