Cloud Functions for Firebase 客戶端 SDK 讓您可以直接從 Firebase 應用調用函數。要以這種方式從您的應用程序調用函數,請在 Cloud Functions 中編寫和部署一個 HTTPS Callable 函數,然後添加客戶端邏輯以從您的應用程序調用該函數。
請務必記住,HTTPS 可調用函數與 HTTP 函數相似但不完全相同。另外,請注意回調簽名在第一代和第二代函數之間發生了變化:
// Adds two numbers to each other.
exports.addnumbers = onCall((request) => {
// Numbers passed from the client.
const firstNumber = request.data.firstNumber;
const secondNumber = request.data.secondNumber;
// Checking that attributes are present and are numbers.
if (!Number.isFinite(firstNumber) || !Number.isFinite(secondNumber)) {
// Throwing an HttpsError so that the client gets the error details.
throw new HttpsError("invalid-argument", "The function must be called " +
"with two arguments \"firstNumber\" and \"secondNumber\" which " +
"must both be numbers.");
}
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: "+",
operationResult: firstNumber + secondNumber,
};
});
在 Cloud Functions(第 2 代)支持 cloudfunctions.net URL 之前,您必須在客戶端代碼中使用不同的初始化程序。不提供函數名稱,而是提供客戶端 SDK 的完整 URL。您的函數的 URL 會在成功的firebase deploy
命令結束時打印出來:
Function URL (shoulddance(us-west1)): https://shoulddance-uvb3o4q2mq-uw.a.run.app
可調用對象與 HTTP 函數有以下主要區別:
- 對於可調用對象,Firebase 身份驗證令牌、FCM 令牌和 App Check 令牌(如果可用)會自動包含在請求中。
-
functions.https.onCall
觸發器自動反序列化請求主體並驗證身份驗證令牌。
適用於 Cloud Functions 第二代及更高版本的 Firebase SDK 可與這些 Firebase 客戶端 SDK 最低版本互操作,以支持 HTTPS 可調用函數:
- 適用於 Apple 平台的 Firebase SDK 10.6.0
- 適用於 Android 的 Firebase SDK 20.2.2
- Firebase 模塊化 Web SDK 9.7.0 版
如果您想向在不受支持的平台上構建的應用程序添加類似功能,請參閱https.onCall
的協議規範。本指南的其餘部分提供有關如何為 Apple 平台、Android、Web、C++ 和 Unity 編寫、部署和調用 HTTPS 可調用函數的說明。
編寫和部署可調用函數
使用functions/v2/https
子包的onCall
方法創建 HTTP 可調用函數。此方法採用具有data
、 auth
、 app
和instanceToken
屬性的event
參數:
// Saves a message to the Firebase Realtime Database but sanitizes the
// text by removing swearwords.
exports.addmessage = onCall((request) => {
// ...
});
例如,對於將文本消息保存到實時數據庫的可調用函數, data
可以包含消息文本以及auth
中的身份驗證信息:
// 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;
可調用函數的位置與調用客戶端的位置之間的距離會造成網絡延遲。要優化性能,請考慮在適用的情況下指定函數位置,並確保在客戶端初始化 SDK時將可調用文件的位置與設置的位置對齊。
您可以選擇附加 App Check 證明,以幫助保護您的後端資源免遭濫用,例如賬單欺詐或網絡釣魚。請參閱為 Cloud Functions 啟用 App Check 強制執行。
發回結果
要將數據發送回客戶端,請返回可以進行 JSON 編碼的數據。例如,要返回加法運算的結果:
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: "+",
operationResult: firstNumber + secondNumber,
};
要在異步操作後返回數據,請返回一個承諾。 promise 返回的數據被發送回客戶端。例如,您可以返回可調用函數寫入實時數據庫的經過清理的文本:
// 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};
})
處理錯誤
為確保客戶端獲得有用的錯誤詳細信息,通過拋出(或返回被拒絕的 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 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.");
}
部署可調用函數
在index.js
中保存完成的可調用函數後,它會在您運行firebase deploy
時與所有其他函數一起部署。要僅部署可調用對象,請使用所示的--only
參數來執行部分部署:
firebase deploy --only functions:addMessage
如果您在部署函數時遇到權限錯誤,請確保將適當的IAM 角色分配給運行部署命令的用戶。
設置客戶端開發環境
確保您滿足任何先決條件,然後將所需的依賴項和客戶端庫添加到您的應用程序。
iOS+
按照說明將Firebase 添加到您的 Apple 應用程序。
使用 Swift Package Manager 安裝和管理 Firebase 依賴項。
- 在 Xcode 中,打開您的應用程序項目,導航至File > Add Packages 。
- 出現提示時,添加 Firebase Apple 平台 SDK 存儲庫:
- 選擇 Cloud Functions 庫。
- 完成後,Xcode 將自動開始在後台解析和下載您的依賴項。
https://github.com/firebase/firebase-ios-sdk
Web version 9
- 按照說明將Firebase 添加到您的 Web 應用程序。確保從終端運行以下命令:
npm install firebase@9.17.2 --save
手動要求 Firebase 核心和 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);
Kotlin+KTX
在您的模塊(應用程序級)Gradle 文件(通常為
<project>/<app-module>/build.gradle
)中,添加 Cloud Functions Android 庫的依賴項。我們建議使用Firebase Android BoM來控制庫版本。dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:31.2.3') // 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' }
通過使用Firebase Android BoM ,您的應用將始終使用兼容版本的 Firebase Android 庫。
(備選)在不使用 BoM 的情況下添加 Firebase 庫依賴項
如果您選擇不使用 Firebase BoM,則必須在其依賴項行中指定每個 Firebase 庫版本。
請注意,如果您在應用中使用多個Firebase 庫,我們強烈建議您使用 BoM 來管理庫版本,以確保所有版本都兼容。
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
在您的模塊(應用程序級)Gradle 文件(通常為
<project>/<app-module>/build.gradle
)中,添加 Cloud Functions Android 庫的依賴項。我們建議使用Firebase Android BoM來控制庫版本。dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:31.2.3') // 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' }
通過使用Firebase Android BoM ,您的應用將始終使用兼容版本的 Firebase Android 庫。
(備選)在不使用 BoM 的情況下添加 Firebase 庫依賴項
如果您選擇不使用 Firebase BoM,則必須在其依賴項行中指定每個 Firebase 庫版本。
請注意,如果您在應用中使用多個Firebase 庫,我們強烈建議您使用 BoM 來管理庫版本,以確保所有版本都兼容。
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' }
初始化客戶端SDK
初始化 Cloud Functions 的實例:
迅速
lazy var functions = Functions.functions()
目標-C
@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions 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();
調用函數
迅速
let addMessageURL = URL(string: "https://addmessage-xyz1234-uc.a.run.app/addMessage")!
functions.httpsCallable(addMessageURL).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
}
}
Web version 9
import { getFunctions, httpsCallableFromURL } from 'firebase/functions';
const functions = getFunctions();
const addMessage = httpsCallableFromURL(
functions,
// the URL of the function
"https://addmessage-xyz1234-uc.a.run.app/addMessage"
);
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
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
// The URL of the function
.getHttpsCallableFromUrl(URL("https://addmessage-xyz1234-uc.a.run.app/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
}
}
在客戶端處理錯誤
如果服務器拋出錯誤或生成的承諾被拒絕,則客戶端會收到錯誤。如果函數返回的錯誤是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]
}
// ...
}
Web version 9
import { getFunctions, httpsCallableFromURL } from "firebase/functions";
const functions = getFunctions();
const addMessage = httpsCallableFromURL(
functions,
// the URL of the function
"https://addmessage-xyz1234-uc.a.run.app/addMessage"
);
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
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 } } }
推薦:使用 App Check 防止濫用
在啟動您的應用程序之前,您應該啟用App Check以幫助確保只有您的應用程序可以訪問您的可調用函數端點。