Cloud Functions for Firebase به شما امکان می دهد توابع را مستقیماً از یک برنامه Firebase فراخوانی کنید. برای فراخوانی یک تابع از برنامه خود به این روش، یک تابع HTTP Callable را در Cloud Functions بنویسید و مستقر کنید و سپس منطق کلاینت را برای فراخوانی تابع از برنامه خود اضافه کنید.
مهم است که به خاطر داشته باشید که توابع فراخوانی HTTP مشابه توابع HTTP هستند اما یکسان نیستند . برای استفاده از توابع قابل فراخوانی HTTP، باید از SDK کلاینت برای پلتفرم خود همراه با API پشتیبان (یا اجرای پروتکل) استفاده کنید. Calable ها این تفاوت های کلیدی را با توابع HTTP دارند:
- با قابلیت فراخوانی، توکنهای Firebase Authentication ، نشانههای FCM ، و نشانههای App Check ، در صورت وجود، بهطور خودکار در درخواستها گنجانده میشوند.
- تریگر به طور خودکار بدنه درخواست را غیرمستقیم می کند و نشانه های تأیید اعتبار را تأیید می کند.
Firebase SDK for Cloud Functions نسل دوم و بالاتر با حداقل نسخههای SDK مشتری Firebase برای پشتیبانی از عملکردهای HTTPS Callable تعامل دارد:
- Firebase SDK برای پلتفرم های Apple 11.5.0
- Firebase SDK برای Android 21.1.0
- Firebase Modular Web SDK نسخه 9.7.0
اگر میخواهید عملکرد مشابهی را به برنامهای که بر روی پلتفرم پشتیبانینشده ساخته شده است اضافه کنید، به مشخصات پروتکل https.onCall
مراجعه کنید. بقیه این راهنما دستورالعمل هایی را در مورد نحوه نوشتن، استقرار و فراخوانی یک تابع قابل فراخوانی HTTP برای پلتفرم های اپل، اندروید، وب، C++ و Unity ارائه می دهد.
تابع فراخوانی را بنویسید و اجرا کنید
مثالهای کد در این بخش بر اساس یک نمونه شروع سریع کامل است که نحوه ارسال درخواستها به یک تابع سمت سرور و دریافت پاسخ با استفاده از یکی از Client SDK را نشان میدهد. برای شروع، ماژول های مورد نیاز را وارد کنید:
Node.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");
پایتون
# Dependencies for callable functions.
from firebase_functions import https_fn, options
# Dependencies for writing to Realtime Database.
from firebase_admin import db, initialize_app
از کنترل کننده درخواست برای پلتفرم خود ( functions.https.onCall
) یا on_call
) برای ایجاد یک تابع قابل فراخوانی HTTPS استفاده کنید. این روش یک پارامتر درخواست را می گیرد:
Node.js
// Saves a message to the Firebase Realtime Database but sanitizes the
// text by removing swearwords.
exports.addmessage = onCall((request) => {
// ...
});
پایتون
@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."""
پارامتر request
شامل دادههای ارسال شده از برنامه مشتری و همچنین زمینه اضافی مانند وضعیت احراز هویت است. برای یک تابع قابل فراخوانی که یک پیام متنی را در Realtime Database ذخیره می کند، به عنوان مثال، data
می توانند متن پیام را همراه با اطلاعات تأیید در auth
داشته باشند:
Node.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;
پایتون
# 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", "")
فاصله بین محل تابع قابل فراخوانی و مکان کلاینت تماس گیرنده می تواند تأخیر شبکه ایجاد کند. برای بهینهسازی عملکرد، مکان عملکرد را در صورت امکان مشخص کنید و مطمئن شوید که وقتی SDK را در سمت کلاینت مقداردهی میکنید، مکان تماسپذیر را با موقعیت مکانی تنظیم کنید.
به صورت اختیاری، میتوانید یک گواهی App Check را ضمیمه کنید تا از منابع پشتیبان خود در برابر سوء استفاده محافظت کنید، مانند تقلب در صورتحساب یا فیشینگ. به فعال کردن اجرای App Check برای Cloud Functions مراجعه کنید.
بازگرداندن نتیجه
برای بازگرداندن دادهها به مشتری، دادههایی را برگردانید که میتوانند JSON کدگذاری شوند. به عنوان مثال، برای برگرداندن نتیجه یک عملیات جمع:
Node.js
// returning result.
return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: "+",
operationResult: firstNumber + secondNumber,
};
پایتون
return {
"firstNumber": first_number,
"secondNumber": second_number,
"operator": "+",
"operationResult": first_number + second_number
}
متن پاکسازی شده از نمونه متن پیام هم به مشتری و هم به Realtime Database بازگردانده می شود. در Node.js، این کار را می توان به صورت ناهمزمان با استفاده از یک وعده جاوا اسکریپت انجام داد:
Node.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};
})
پایتون
# 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}
پیکربندی CORS (اشتراک گذاری منابع متقابل)
از گزینه cors
برای کنترل اینکه کدام مبدا می تواند به عملکرد شما دسترسی داشته باشد استفاده کنید.
به طور پیشفرض، توابع قابل فراخوانی CORS را برای اجازه دادن به درخواستها از همه مبدا پیکربندی کردهاند. برای اجازه دادن به برخی از درخواستهای متقاطع، اما نه همه، فهرستی از دامنههای خاص یا عبارات معمولی را که باید مجاز باشند، ارسال کنید. به عنوان مثال:
Node.js
const { onCall } = require("firebase-functions/v2/https");
exports.getGreeting = onCall(
{ cors: [/firebase\.com$/, "https://flutter.com"] },
(request) => {
return "Hello, world!";
}
);
برای منع درخواست های متقاطع، خط مشی cors
را روی false
تنظیم کنید.
رسیدگی به خطاها
برای اطمینان از اینکه مشتری جزئیات خطای مفیدی را دریافت میکند https_fn.HttpsError
با پرتاب کردن (یا برای Node.js که یک Promise را رد کرده است) نمونهای از functions.https.HttpsError
را برگرداند. خطا دارای یک ویژگی code
است که می تواند یکی از مقادیر فهرست شده در کدهای وضعیت gRPC باشد. خطاها همچنین دارای یک message
رشته ای هستند که به طور پیش فرض یک رشته خالی است. آنها همچنین می توانند یک فیلد details
اختیاری با مقدار دلخواه داشته باشند. اگر خطایی غیر از خطای HTTPS از توابع شما پرتاب شود، کلاینت شما در عوض یک خطا با پیام INTERNAL
و کد internal
دریافت می کند.
به عنوان مثال، یک تابع می تواند خطاهای اعتبارسنجی و احراز هویت داده ها را با پیام های خطا ارسال کند تا به مشتری تماس گیرنده بازگردد:
Node.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.");
}
پایتون
# 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.")
تابع فراخوانی را اجرا کنید
پس از اینکه یک تابع قابل فراخوان کامل را در index.js
ذخیره کردید، با اجرای firebase deploy
همراه با سایر توابع مستقر می شود. برای استقرار فقط فراخوانی، از آرگومان --only
همانطور که نشان داده شده است برای انجام استقرار جزئی استفاده کنید:
firebase deploy --only functions:addMessage
اگر هنگام استقرار توابع با خطاهای مجوز مواجه شدید، مطمئن شوید که نقش های IAM مناسب به کاربری که دستورات استقرار را اجرا می کند اختصاص داده شده است.
محیط توسعه مشتری خود را تنظیم کنید
مطمئن شوید که پیش نیازها را برآورده می کنید، سپس وابستگی ها و کتابخانه های مشتری مورد نیاز را به برنامه خود اضافه کنید.
iOS+
دستورالعمل ها را برای افزودن Firebase به برنامه Apple خود دنبال کنید.
برای نصب و مدیریت وابستگی های Firebase از Swift Package Manager استفاده کنید.
- در Xcode، با باز بودن پروژه برنامه، به File > Add Packages بروید.
- هنگامی که از شما خواسته شد، مخزن SDK پلتفرم های Apple Firebase را اضافه کنید:
- کتابخانه Cloud Functions را انتخاب کنید.
- پرچم
-ObjC
را به بخش Other Linker Flags تنظیمات ساخت هدف خود اضافه کنید. - پس از اتمام، Xcode به طور خودکار شروع به حل و دانلود وابستگی های شما در پس زمینه می کند.
https://github.com/firebase/firebase-ios-sdk.git
Web
- دستورالعمل ها را برای افزودن Firebase به برنامه وب خود دنبال کنید. حتماً دستور زیر را از ترمینال خود اجرا کنید:
npm install firebase@11.0.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);
اندروید
دستورالعمل ها را برای افزودن Firebase به برنامه Android خود دنبال کنید.
در فایل Gradle ماژول (سطح برنامه) خود (معمولا
<project>/<app-module>/build.gradle.kts
یا<project>/<app-module>/build.gradle
)، وابستگی را برای Cloud Functions اضافه کنید. کتابخانه برای اندروید توصیه میکنیم از Firebase Android BoM برای کنترل نسخهسازی کتابخانه استفاده کنید.dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:33.6.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") }
با استفاده از Firebase Android BoM ، برنامه شما همیشه از نسخههای سازگار کتابخانههای Firebase Android استفاده میکند.
به دنبال یک ماژول کتابخانه خاص کاتلین هستید؟ از اکتبر 2023 ( Firebase BoM 32.5.0) ، توسعه دهندگان Kotlin و Java می توانند به ماژول کتابخانه اصلی وابسته باشند (برای جزئیات، به سؤالات متداول در مورد این ابتکار مراجعه کنید).(جایگزین) وابستگی های کتابخانه Firebase را بدون استفاده از BoM اضافه کنید
اگر تصمیم گرفتید از 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:21.1.0") }
SDK مشتری را راه اندازی کنید
نمونه ای از Cloud Functions را راه اندازی کنید:
سویفت
lazy var functions = Functions.functions()
هدف-C
@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];
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();
تابع را فراخوانی کنید
سویفت
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 isEqual:@"com.firebase.functions"]) {
FIRFunctionsErrorCode code = error.code;
NSString *message = error.localizedDescription;
NSObject *details = error.userInfo[@"details"];
}
// ...
}
self->_resultField.text = result.data[@"text"];
}];
Web
var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
var sanitizedMessage = result.data.text;
});
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);
}
وحدت
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 isEqual:@"com.firebase.functions"]) {
FIRFunctionsErrorCode code = error.code;
NSString *message = error.localizedDescription;
NSObject *details = error.userInfo[@"details"];
}
// ...
}
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;
// ...
});
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);
// ...
وحدت
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 از سوء استفاده جلوگیری کنید
قبل از اینکه برنامه خود را راه اندازی کنید، باید App Check فعال کنید تا مطمئن شوید که فقط برنامه های شما می توانند به نقاط پایانی عملکرد قابل فراخوانی شما دسترسی داشته باشند.