קריאה לפונקציות דרך בקשות HTTP

אפשר להפעיל פונקציה באמצעות בקשת HTTP עם handler של בקשות. כך אפשר להפעיל פונקציה באמצעות ה-methods הבאות של HTTP: GET,‏ POST,‏ PUT,‏ DELETE ו-OPTIONS.

במדריך הזה אנחנו יוצאים מנקודת הנחה שביצעתם את משימות ההגדרה שמפורטות במדריך לתחילת העבודה עם Node.js ו-Python, או את משימות ההגדרה של הגרסה הניסיונית של Dart SDK.

אפשרויות HTTP נוספות

אפשרות תיאור
region בפונקציות HTTP אפשר לציין מערך של אזורים וגם אזור אחד. כשמציינים כמה אזורים, נפרס מופע נפרד של הפונקציה בכל אזור.
‫timeoutSeconds (timeout_sec ל-Python) בפונקציות HTTP אפשר לציין זמן קצוב לתפוגה של עד שעה.
cors פונקציות HTTP יכולות לציין כללי מדיניות של CORS. אפשר להגדיר את זה ל-true כדי לאפשר את כל המקורות, או ל-string, regex או array כדי לציין מקורות מותרים. אם לא מגדירים את המדיניות במפורש, ברירת המחדל היא false/אין כללי מדיניות של CORS.

הגדרת CORS (שיתוף משאבים ממקורות שונים)

משתמשים באפשרות cors כדי לקבוע לאילו מקורות תהיה גישה לפונקציה. כברירת מחדל, לפונקציות HTTP אין הגדרות CORS, כלומר כל בקשה ממקורות שונים לפונקציה תגרום לשגיאה הבאה:

request has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

אפשר גם להשבית את CORS באופן מפורש על ידי הגדרת האפשרות cors לערך false בפונקציה.

כדי לאפשר רק חלק מהבקשות ממקורות שונים, אפשר להעביר רשימה של דומיינים ספציפיים או ביטויים רגולריים שרוצים לאפשר. לדוגמה, אם אתם הבעלים של הדומיינים firebase.com ו-flutter.com, ולדומיין firebase.com יכולים להיות הרבה תת-דומיינים, אתם יכולים להגדיר את האפשרות cors באופן הבא:

Node.js

const { onRequest } = require("firebase-functions/v2/https");

exports.sayHello = onRequest(
  { cors: [/firebase\.com$/, "https://flutter.com"] },
  (req, res) => {
    res.status(200).send("Hello world!");
  }
);

Python

from firebase_functions import https_fn, options

@https_fn.on_request(
    cors=options.CorsOptions(
        cors_origins=[r"firebase\.com$", r"https://flutter\.com"],
        cors_methods=["get", "post"],
    )
)
def say_hello(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

‫Dart (ניסיוני)

import 'package:firebase_functions/firebase_functions.dart';

void main() {
  runFunctions((firebase) {
    firebase.https.onRequest(
      name: 'sayHello',
      options: const HttpsOptions(
        cors: Cors([RegExp(r'^https:\/\/firebase\.com$'), 'https://flutter.com']),
      ),
      (request) async => Response(200, body: 'Hello world!'),
    );
  });
}

אם הפונקציה צריכה להיות זמינה לכולם, למשל אם היא משרתת API או אתר ציבוריים, צריך להגדיר את המדיניות cors לערך true.

הפעלת פונקציה באמצעות בקשת HTTP

משתמשים ב-handler של הבקשות בפלטפורמה כדי ליצור פונקציה שמטפלת באירועי HTTP. הדוגמאות בקטע הזה מבוססות על דוגמה של "שרת זמן" שמופעל כששולחים בקשת HTTP GET לנקודת הקצה של הפונקציות. הפונקציה לדוגמה מאחזרת את זמן השרת הנוכחי, מעצבת את הזמן כפי שצוין בפרמטר של שאילתת כתובת ה-URL ושולחת את התוצאה בתגובת ה-HTTP.

שימוש באובייקטים של בקשות ותגובות

אובייקט הבקשה נותן לכם גישה למאפיינים של בקשת ה-HTTP שנשלחה על ידי הלקוח, ואובייקט התגובה מאפשר לכם לשלוח תגובה בחזרה ללקוח.

Node.js

exports.date = onRequest(
    {timeoutSeconds: 1200, region: ["us-west1", "us-east1"]},
    (req, res) => {
// ...
});

Python

@https_fn.on_request(cors=options.CorsOptions(cors_origins="*", cors_methods=["get", "post"]))
def date(req: https_fn.Request) -> https_fn.Response:
    """Get the server's local date and time."""

‫Dart (ניסיוני)

void main() {
  runFunctions((firebase) {
    firebase.https.onRequest(name: 'date', (request) async {

שימוש באפליקציות קיימות של Express או Flask

באמצעות האפליקציה כארגומנט של ה-request handler, אפשר להעביר אפליקציה מלאה לפונקציית HTTP:

Node.js

const { onRequest } = require('firebase-functions/v2/https');

const express = require('express');
const app = express();

// Add middleware to authenticate requests
app.use(myMiddleware);

// build multiple CRUD interfaces:
app.get('/:id', (req, res) => res.send(Widgets.getById(req.params.id)));
app.post('/', (req, res) => res.send(Widgets.create()));
app.put('/:id', (req, res) => res.send(Widgets.update(req.params.id, req.body)));
app.delete('/:id', (req, res) => res.send(Widgets.delete(req.params.id)));
app.get('/', (req, res) => res.send(Widgets.list()));

// Expose Express API as a single Cloud Function:
exports.widgets = onRequest(app);

Python

from firebase_admin import initialize_app, db
from firebase_functions import https_fn
import flask

initialize_app()
app = flask.Flask(__name__)

# Build multiple CRUD interfaces:


@app.get("/widgets")
@app.get("/widgets/<id>")
def get_widget(id=None):
    if id is not None:
        return db.reference(f"/widgets/{id}").get()
    else:
        return db.reference("/widgets").get()


@app.post("/widgets")
def add_widget():
    new_widget = flask.request.get_data(as_text=True)
    db.reference("/widgets").push(new_widget)
    return flask.Response(status=201, response="Added widget")


# Expose Flask app as a single Cloud Function:


@https_fn.on_request()
def httpsflaskexample(req: https_fn.Request) -> https_fn.Response:
    with app.request_context(req.environ):
        return app.full_dispatch_request()

הפעלה של פונקציית HTTP

אחרי שפורסים פונקציית HTTP, אפשר להפעיל אותה באמצעות כתובת URL ייחודית משלה. צריך להשתמש בכתובת ה-URL המדויקת שמופיעה בפלט של ה-CLI אחרי הפריסה.

לדוגמה, כתובת ה-URL להפעלת date() נראית כך:

https://us-central1-<project-id>.cloudfunctions.net/date

בניתוב של אפליקציות Express ו-Flask, שם הפונקציה מתווסף כתחילית לנתיבי כתובות ה-URL באפליקציה שאתם מגדירים.

קריאת ערכים מהבקשה

בדוגמה של הפונקציה date(), הפונקציה בודקת גם את הפרמטר של כתובת ה-URL וגם את גוף הבקשה כדי למצוא ערך של format, ולהגדיר את הפורמט של התאריך והשעה:

Node.js

let format = req.query.format;
format = req.body.format;

Python

format = req.args["format"] if "format" in req.args else None

‫Dart (ניסיוני)

var format = request.url.queryParameters['format'];
final bodyString = await request.readAsString();
try {
  if (bodyString.isNotEmpty) {
    final body = jsonDecode(bodyString) as Map<String, dynamic>;
    format = body['format'] as String?;
  }
} catch (e) {
  return Response.badRequest(body: 'invalid JSON');
}

סיום פונקציות HTTP

אחרי אחזור זמן השרת ועיצובו, הפונקציה date() מסתיימת בשליחת התוצאה בתגובת ה-HTTP:

Node.js

תמיד צריך לסיים פונקציית HTTP באמצעות send(),‏ redirect() או end(). אחרת, יכול להיות שהפונקציה תמשיך לפעול והמערכת תסיים אותה באופן מאולץ. אפשר לעיין גם במאמר Sync, Async and Promises.

const formattedDate = moment().format(`${format}`);
logger.log("Sending formatted date:", formattedDate);
res.status(200).send(formattedDate);

Python

formatted_date = datetime.now().strftime(format)
print(f"Sending Formatted date: {formatted_date}")
return https_fn.Response(formatted_date)

‫Dart (ניסיוני)

final formattedDate = DateFormat(format).format(DateTime.now());
print('Sending formatted date: $formattedDate');
return Response.ok(formattedDate);

שילוב עם אירוח ב-Firebase

אפשר לחבר פונקציית HTTP אל Firebase Hosting. אפשר להעביר בקשות באתר Firebase Hosting דרך שרת proxy לפונקציות HTTP ספציפיות. כך גם תוכלו להשתמש בדומיין מותאם אישית משלכם עם פונקציית HTTP. מידע נוסף על קישור Cloud Functions אל Firebase Hosting