अपने एनवायरमेंट को कॉन्फ़िगर करना

अक्सर आपको अपने फ़ंक्शन के लिए अतिरिक्त कॉन्फ़िगरेशन की ज़रूरत होगी. जैसे, तीसरे पक्ष के एपीआई की कुंजियां या ट्यून की जा सकने वाली सेटिंग. Firebase SDK टूल में, Cloud Functions के लिए एनवायरमेंट कॉन्फ़िगरेशन की सुविधा पहले से मौजूद होती है. इससे, आपके प्रोजेक्ट के लिए इस तरह का डेटा सेव करना और वापस पाना आसान हो जाता है.

आपके पास इनमें से कोई एक विकल्प चुनने की सुविधा होती है:

  • पैरामीटर वाला कॉन्फ़िगरेशन (ज़्यादातर स्थितियों के लिए यह विकल्प चुनने का सुझाव दिया जाता है). इससे, मज़बूत टाइप वाला एनवायरमेंट कॉन्फ़िगरेशन मिलता है. इसमें ऐसे पैरामीटर होते हैं जिनकी पुष्टि डिप्लॉयमेंट के समय की जाती है. इससे गड़बड़ियां नहीं होती हैं और डीबग करना आसान हो जाता है.
  • एनवायरमेंट वैरिएबल का फ़ाइल-आधारित कॉन्फ़िगरेशन. इस तरीके से, एनवायरमेंट वैरिएबल लोड करने के लिए, आपको मैन्युअल तरीके से dotenv फ़ाइल बनानी होती है.

ज़्यादातर इस्तेमाल के मामलों के लिए, पैरामीटर वाला कॉन्फ़िगरेशन चुनने का सुझाव दिया जाता है. इस तरीके से, कॉन्फ़िगरेशन की वैल्यू, रनटाइम और डिप्लॉयमेंट, दोनों के दौरान उपलब्ध होती हैं. साथ ही, जब तक सभी पैरामीटर की वैल्यू मान्य नहीं होती, तब तक डिप्लॉयमेंट नहीं किया जा सकता. इसके उलट, एनवायरमेंट वैरिएबल के साथ कॉन्फ़िगरेशन, डिप्लॉयमेंट के समय उपलब्ध नहीं होता.

पैरामीटर वाला कॉन्फ़िगरेशन

Cloud Functions for Firebase आपके कोडबेस में कॉन्फ़िगरेशन पैरामीटर को डिक्लेरेटिव तरीके से तय करने के लिए एक इंटरफ़ेस उपलब्ध कराता है. इन पैरामीटर की वैल्यू, फ़ंक्शन के डिप्लॉयमेंट, डिप्लॉयमेंट और रनटाइम के विकल्प सेट करने, और एक्ज़ीक्यूशन के दौरान उपलब्ध होती है. इसका मतलब है कि जब तक सभी पैरामीटर की वैल्यू मान्य नहीं होती, तब तक सीएलआई, डिप्लॉयमेंट को ब्लॉक कर देगा.

Node.js

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

// Define some parameters
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

# To use configured parameters inside the config for a function, provide them
# directly. To use them at runtime, call .value() on them.
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

पैरामीटर वाले कॉन्फ़िगरेशन वैरिएबल के साथ किसी फ़ंक्शन को डिप्लॉय करते समय, Firebase सीएलआई सबसे पहले .env फ़ाइलों से उनकी वैल्यू लोड करने की कोशिश करता है. अगर वे फ़ाइलों में मौजूद नहीं हैं और कोई default सेट नहीं है, तो सीएलआई, डिप्लॉयमेंट के दौरान वैल्यू के लिए प्रॉम्प्ट करेगा. इसके बाद, उनकी वैल्यू को functions/ डायरेक्ट्री में .env.<project_ID> नाम की .env फ़ाइल में अपने-आप सेव कर देगा:

$ firebase deploy
i  functions: preparing codebase default for deployment
? Enter a string value for ENVIRONMENT: prod
i  functions: Writing new parameter values to disk: .env.projectId
…
$ firebase deploy
i  functions: Loaded environment variables from .env.projectId

डेवलपमेंट के वर्कफ़्लो के आधार पर, जनरेट की गई .env.<project_ID> फ़ाइल को वर्शन कंट्रोल में जोड़ना काम का हो सकता है.

ग्लोबल स्कोप में पैरामीटर का इस्तेमाल करना

डिप्लॉयमेंट के दौरान, आपके पैरामीटर की असली वैल्यू मिलने से पहले, आपके फ़ंक्शन का कोड लोड और उसकी जांच की जाती है. इसका मतलब है कि ग्लोबल स्कोप के दौरान पैरामीटर की वैल्यू फ़ेच करने पर, डिप्लॉयमेंट में गड़बड़ी होती है. ऐसे मामलों में जहां आपको ग्लोबल वैल्यू को शुरू करने के लिए किसी पैरामीटर का इस्तेमाल करना है, वहां onInit() को शुरू करने वाले कॉलबैक का इस्तेमाल करें. यह कॉलबैक, प्रोडक्शन में किसी भी फ़ंक्शन के चलने से पहले चलता है. हालांकि, इसे डिप्लॉयमेंट के समय कॉल नहीं किया जाता. इसलिए, यह पैरामीटर की वैल्यू को ऐक्सेस करने के लिए सुरक्षित जगह है.

Node.js

const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v2/core');

const apiKey = defineSecret('GOOGLE_API_KEY');

let genAI;
onInit(() => {
  genAI = new GoogleGenerativeAI(apiKey.value());
})

Python

from firebase_functions.core import init
from firebase_functions.params import StringParam, PROJECT_ID
import firebase_admin
import vertexai

location = StringParam("LOCATION")

x = "hello"

@init
def initialize():
  # Note: to write back to a global, you'll need to use the "global" keyword
  # to avoid creating a new local with the same name.
  global x
  x = "world"
  firebase_admin.initialize_app()
  vertexai.init(PROJECT_ID.value, location.value)

अगर Secret टाइप के पैरामीटर का इस्तेमाल किया जाता है, तो ध्यान दें कि वे सिर्फ़ उन फ़ंक्शन की प्रोसेस में उपलब्ध होते हैं जिन्होंने सीक्रेट को बाइंड किया है. अगर किसी सीक्रेट को सिर्फ़ कुछ फ़ंक्शन में बाइंड किया जाता है, तो उसका इस्तेमाल करने से पहले, यह देखें कि secret.value() फ़ॉल्सी है या नहीं.

सीएलआई के व्यवहार को कॉन्फ़िगर करना

पैरामीटर को Options ऑब्जेक्ट के साथ कॉन्फ़िगर किया जा सकता है. यह ऑब्जेक्ट, सीएलआई के वैल्यू के लिए प्रॉम्प्ट करने के तरीके को कंट्रोल करता है. यहां दिए गए उदाहरण में, फ़ोन नंबर के फ़ॉर्मैट की पुष्टि करने, चुनने का आसान विकल्प देने, और Firebase प्रोजेक्ट से चुनने के विकल्प को अपने-आप भरने के लिए विकल्प सेट किए गए हैं:

Node.js

const { defineString } = require('firebase-functions/params');

const welcomeMessage = defineString('WELCOME_MESSAGE', {default: 'Hello World',
description: 'The greeting that is returned to the caller of this function'});

const onlyPhoneNumbers = defineString('PHONE_NUMBER', {
  input: {
    text: {
      validationRegex: /\d{3}-\d{3}-\d{4}/,
      validationErrorMessage: "Please enter
a phone number in the format XXX-YYY-ZZZZ"
    },
  },
});

const selectedOption = defineString('PARITY', {input: params.select(["odd", "even"])});

const memory = defineInt("MEMORY", {
  description: "How much memory do you need?",
  input: params.select({ "micro": 256, "chonky": 2048 }),
});

const extensions = defineList("EXTENSIONS", {
  description: "Which file types should be processed?",
  input: params.multiSelect(["jpg", "tiff", "png", "webp"]),
});

const storageBucket = defineString('BUCKET', {
  description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets",
  input: params.PICK_STORAGE_BUCKET,
});

Python

from firebase_functions.params import (
    StringParam,
    ListParam,
    TextInput,
    SelectInput,
    SelectOptions,
    ResourceInput,
    ResourceType,
)

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

WELCOME_MESSAGE = StringParam(
    "WELCOME_MESSAGE",
    default="Hello World",
    description="The greeting that is returned to the caller of this function",
)

ONLY_PHONE_NUMBERS = StringParam(
    "PHONE_NUMBER",
    input=TextInput(
        validation_regex="\d{3}-\d{3}-\d{4}",
        validation_error_message="Please enter a phone number in the format XXX-YYY-XXX",
    ),
)

SELECT_OPTION = StringParam(
    "PARITY",
    input=SelectInput([SelectOptions(value="odd"), SelectOptions(value="even")]),
)

STORAGE_BUCKET = StringParam(
    "BUCKET",
    input=ResourceInput(type=ResourceType.STORAGE_BUCKET),
    description="This will automatically populate the selector field with the deploying Cloud Project's storage buckets",
)

पैरामीटर के टाइप

पैरामीटर वाले कॉन्फ़िगरेशन में, पैरामीटर की वैल्यू के लिए मज़बूत टाइपिंग की सुविधा मिलती है. साथ ही, इसमें Cloud Secret Manager के सीक्रेट भी इस्तेमाल किए जा सकते हैं. इन टाइप की फ़ाइलें इस्तेमाल की जा सकती हैं:

  • सीक्रेट
  • स्ट्रिंग
  • बूलियन
  • पूर्णांक
  • फ़्लोट
  • सूची (Node.js)
  • JSON सीक्रेट (Node.js)

पैरामीटर तय करने के लिए, फ़ंक्शन के बारे में जानकारी पाने के लिए, params नेमस्पेस रेफ़रंस देखें.

पैरामीटर की वैल्यू और एक्सप्रेशन

Firebase, डिप्लॉयमेंट के समय और आपके फ़ंक्शन के एक्ज़ीक्यूट होने के दौरान, दोनों ही स्थितियों में आपके पैरामीटर की वैल्यू का आकलन करता है. इन दो एनवायरमेंट की वजह से, पैरामीटर की वैल्यू की तुलना करते समय और अपने फ़ंक्शन के लिए रनटाइम के विकल्प सेट करने के लिए उनका इस्तेमाल करते समय, ज़्यादा सावधानी बरतनी चाहिए.

किसी पैरामीटर को रनटाइम के विकल्प के तौर पर अपने फ़ंक्शन में पास करने के लिए, उसे सीधे तौर पर पास करें:

Node.js

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

export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

इसके अलावा, अगर आपको यह जानने के लिए किसी पैरामीटर की तुलना करनी है कि कौनसा विकल्प चुनना है, तो आपको वैल्यू की जांच करने के बजाय, पहले से मौजूद तुलना करने वाले टूल का इस्तेमाल करना होगा:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const environment = params.defineString(ENVIRONMENT, {default: 'dev'});

// use built-in comparators
const minInstancesConfig = environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

ENVIRONMENT = StringParam("ENVIRONMENT", default="dev")
MIN_INSTANCES = ENVIRONMENT.equals("PRODUCTION").then(10, 0)

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

सिर्फ़ रनटाइम के दौरान इस्तेमाल किए जाने वाले पैरामीटर और पैरामीटर एक्सप्रेशन को उनके value फ़ंक्शन से ऐक्सेस किया जा सकता है:

Node.js

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

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import StringParam

WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

@https_fn.on_request()
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

पहले से मौजूद पैरामीटर

Cloud Functions SDK टूल में, पहले से तय किए गए तीन पैरामीटर उपलब्ध हैं. ये firebase-functions/params सबपैकेज में उपलब्ध हैं:

Node.js

  • projectID — वह Cloud प्रोजेक्ट जिसमें फ़ंक्शन चल रहा है.
  • databaseURL — Realtime Database के उस इंस्टेंस का यूआरएल जो फ़ंक्शन से जुड़ा है. यह तब उपलब्ध होता है, जब Firebase प्रोजेक्ट में यह सुविधा चालू हो.
  • storageBucket — Cloud Storage का वह बकेट जो फ़ंक्शन से जुड़ा है. यह तब उपलब्ध होता है, जब Firebase प्रोजेक्ट में यह सुविधा चालू हो.

Python

  • PROJECT_ID — वह Cloud प्रोजेक्ट जिसमें फ़ंक्शन चल रहा है.
  • DATABASE_URL — Realtime Database के उस इंस्टेंस का यूआरएल जो फ़ंक्शन से जुड़ा है. यह तब उपलब्ध होता है, जब Firebase प्रोजेक्ट में यह सुविधा चालू हो.
  • STORAGE_BUCKET — Cloud Storage का वह बकेट जो फ़ंक्शन से जुड़ा है. यह तब उपलब्ध होता है, जब Firebase प्रोजेक्ट में यह सुविधा चालू हो.

ये सभी पैरामीटर, उपयोगकर्ता की ओर से तय की गई स्ट्रिंग पैरामीटर की तरह काम करते हैं. हालांकि, इनकी वैल्यू हमेशा Firebase सीएलआई को पता होती है. इसलिए, डिप्लॉयमेंट के दौरान इनकी वैल्यू के लिए कभी भी प्रॉम्प्ट नहीं किया जाएगा. साथ ही, इन्हें .env फ़ाइलों में सेव भी नहीं किया जाएगा.

सीक्रेट पैरामीटर

Secret टाइप के पैरामीटर, defineSecret() का इस्तेमाल करके तय किए गए स्ट्रिंग पैरामीटर होते हैं. इनकी वैल्यू, Cloud Secret Manager में सेव होती है. सीक्रेट पैरामीटर, स्थानीय .env फ़ाइल की जांच करने और फ़ाइल में नई वैल्यू लिखने के बजाय, Cloud Secret Manager में मौजूद होने की जांच करते हैं. साथ ही, डिप्लॉयमेंट के दौरान, नए सीक्रेट की वैल्यू के लिए इंटरैक्टिव तरीके से प्रॉम्प्ट करते हैं.

सीक्रेट पैरामीटर को उन अलग-अलग फ़ंक्शन से बाइंड किया जाना चाहिए जिनके पास उनका ऐक्सेस होना चाहिए:

Node.js

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

export const postToDiscord = onRequest(
  { secrets: [discordApiKey] },
  (req, res) => {
  const apiKey = discordApiKey.value();
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import SecretParam

DISCORD_API_KEY = SecretParam('DISCORD_API_KEY')

@https_fn.on_request(secrets=[DISCORD_API_KEY])
def post_to_discord(req):
    api_key = DISCORD_API_KEY.value

सीक्रेट की वैल्यू, फ़ंक्शन के एक्ज़ीक्यूशन तक छिपी रहती हैं. इसलिए, फ़ंक्शन को कॉन्फ़िगर करते समय उनका इस्तेमाल नहीं किया जा सकता.

स्ट्रक्चर्ड JSON सीक्रेट

अगर आपके पास एक से ज़्यादा कॉन्फ़िगरेशन वैल्यू हैं जो लॉजिकल तौर पर एक-दूसरे से जुड़ी हैं (उदाहरण के लिए, तीसरे पक्ष की सेवा के लिए सेटिंग), तो उन्हें defineJsonSecret() का इस्तेमाल करके, एक ही सीक्रेट में स्ट्रक्चर्ड JSON ऑब्जेक्ट के तौर पर सेव किया जा सकता है. इस तरीके से, अपने कॉन्फ़िगरेशन को व्यवस्थित किया जा सकता है. साथ ही, Cloud Secret Manager के मुफ़्त टियर का ज़्यादा बेहतर तरीके से इस्तेमाल किया जा सकता है. इसके लिए, एक ही सीक्रेट में, कॉन्फ़िगरेशन की एक-दूसरे से जुड़ी वैल्यू के ग्रुप को सेव किया जा सकता है.

Secret Manager में सेव की गई वैल्यू, मान्य JSON स्ट्रिंग होनी चाहिए. .value() को ऐक्सेस करने पर, SDK टूल, JSON स्ट्रिंग को JavaScript ऑब्जेक्ट में अपने-आप पार्स कर देगा.

उदाहरण:

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

// Define a single secret to hold all configuration for some API
const someApiConfig = defineJsonSecret('SOMEAPI_CONFIG');

exports.myApi = onRequest(
  { secrets: [someApiConfig] },
  (req, res) => {
    // someApiConfig.value() automatically parses the JSON secret
    const { apiKey, webhookSecret, clientId } = someApiConfig.value();

    // Now you can use apiKey, webhookSecret, clientId
    // ...
  }
);

SOMEAPI_CONFIG सीक्रेट बनाने के लिए, आपको Secret Manager में इसकी वैल्यू को इस तरह की JSON स्ट्रिंग पर सेट करना होगा:

{
  "apiKey": "key_...",
  "webhookSecret": "secret_...",
  "clientId": "client_..."
}

अगर सीक्रेट की वैल्यू, मान्य JSON नहीं है, तो someApiConfig.value() को ऐक्सेस करने पर, रनटाइम में गड़बड़ी होगी.

एनवायरमेंट वैरिएबल

Cloud Functions for Firebase dotenv फ़ाइल फ़ॉर्मैट के साथ काम करता है. इसका इस्तेमाल, .env फ़ाइल में तय किए गए एनवायरमेंट वैरिएबल को आपके ऐप्लिकेशन के रनटाइम में लोड करने के लिए किया जाता है. डिप्लॉय होने के बाद, एनवायरमेंट वैरिएबल को process.env इंटरफ़ेस (Node.js पर आधारित प्रोजेक्ट में) या os.environ (Python पर आधारित प्रोजेक्ट में) के ज़रिए पढ़ा जा सकता है.

अपने एनवायरमेंट को इस तरह कॉन्फ़िगर करने के लिए, अपने प्रोजेक्ट में .env फ़ाइल बनाएं, उसमें ज़रूरी वैरिएबल जोड़ें, और डिप्लॉय करें:

  1. अपनी functions/ डायरेक्ट्री में .env फ़ाइल बनाएं:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. बदलाव करने के लिए .env फ़ाइल खोलें और उसमें ज़रूरी कुंजियां जोड़ें. उदाहरण के लिए:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. फ़ंक्शन डिप्लॉय करें और पुष्टि करें कि एनवायरमेंट वैरिएबल लोड हो गए हैं:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

अपने कस्टम एनवायरमेंट वैरिएबल डिप्लॉय होने के बाद, आपका फ़ंक्शन कोड उन्हें ऐक्सेस कर सकता है:

Node.js

// Responds with "Hello Earth and Humans"
exports.hello = onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

Python

import os

@https_fn.on_request()
def hello(req):
    return https_fn.Response(
        f"Hello {os.environ.get('PLANET')} and {os.environ.get('AUDIENCE')}"
    )

एनवायरमेंट वैरिएबल के एक से ज़्यादा सेट डिप्लॉय करना

अगर आपको अपने Firebase प्रोजेक्ट के लिए एनवायरमेंट वैरिएबल का कोई दूसरा सेट चाहिए (जैसे, स्टेजिंग बनाम प्रोडक्शन), तो .env.<project or alias> फ़ाइल बनाएं और उसमें अपने प्रोजेक्ट के लिए खास एनवायरमेंट वैरिएबल लिखें. डिप्लॉय किए गए सभी फ़ंक्शन में, .env और प्रोजेक्ट के लिए खास .env फ़ाइलों (अगर वे मौजूद हैं) के एनवायरमेंट वैरिएबल शामिल किए जाएंगे.

उदाहरण के लिए, किसी प्रोजेक्ट में ये तीन फ़ाइलें शामिल हो सकती हैं. इनमें डेवलपमेंट और प्रोडक्शन के लिए थोड़ी अलग वैल्यू हो सकती हैं:

.env .env.dev .env.prod
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

इन अलग-अलग फ़ाइलों में दी गई वैल्यू के हिसाब से, आपके टारगेट प्रोजेक्ट के आधार पर, आपके फ़ंक्शन के साथ डिप्लॉय किए गए एनवायरमेंट वैरिएबल का सेट अलग-अलग होगा:

$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Dev Humans

$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Prod Humans

रिज़र्व किए गए एनवायरमेंट वैरिएबल

कुछ एनवायरमेंट वैरिएबल की कुंजियां, इंटरनल इस्तेमाल के लिए रिज़र्व की गई हैं. अपनी .env फ़ाइलों में इनमें से किसी भी कुंजी का इस्तेमाल न करें:

  • X_GOOGLE_ से शुरू होने वाली सभी कुंजियां
  • EXT_ से शुरू होने वाली सभी कुंजियां
  • FIREBASE_ से शुरू होने वाली सभी कुंजियां
  • यहां दी गई सूची में मौजूद कोई भी कुंजी:
  • CLOUD_RUNTIME_CONFIG
  • ENTRY_POINT
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • FUNCTION_NAME
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCTION_IDENTITY
  • FUNCTION_REGION
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICE
  • K_REVISION
  • PORT
  • K_CONFIGURATION

संवेदनशील कॉन्फ़िगरेशन की जानकारी सेव करना और उसे ऐक्सेस करना

.env फ़ाइलों में सेव किए गए एनवायरमेंट वैरिएबल का इस्तेमाल, फ़ंक्शन के कॉन्फ़िगरेशन के लिए किया जा सकता है. हालांकि, इन्हें डेटाबेस क्रेडेंशियल या एपीआई की कुंजियों जैसी संवेदनशील जानकारी सेव करने का सुरक्षित तरीका नहीं माना जाना चाहिए. यह खास तौर पर तब ज़रूरी है, जब .env फ़ाइलों को सोर्स कंट्रोल में चेक किया जाता है.

संवेदनशील कॉन्फ़िगरेशन की जानकारी सेव करने में आपकी मदद करने के लिए, Cloud Functions for Firebase को Google Cloud Secret Managerके साथ इंटिग्रेट किया गया है. यह एन्क्रिप्ट की गई सेवा, कॉन्फ़िगरेशन की वैल्यू को सुरक्षित तरीके से सेव करती है. साथ ही, ज़रूरत पड़ने पर आपके फ़ंक्शन से आसानी से ऐक्सेस करने की अनुमति देती है.

सीक्रेट बनाना और उसका इस्तेमाल करना

सीक्रेट बनाने के लिए, Firebase सीएलआई का इस्तेमाल करें.

सीक्रेट बनाने और उसका इस्तेमाल करने के लिए:

  1. अपने स्थानीय प्रोजेक्ट डायरेक्ट्री के रूट से, यह कमांड चलाएं:

    firebase functions:secrets:set SECRET_NAME

  2. SECRET_NAME के लिए कोई वैल्यू डालें.

    सीएलआई, सफलता का मैसेज दिखाता है और चेतावनी देता है कि बदलाव को लागू करने के लिए, आपको फ़ंक्शन डिप्लॉय करने होंगे.

  3. डिप्लॉय करने से पहले, पक्का करें कि आपके फ़ंक्शन के कोड में, secrets विकल्प का इस्तेमाल करके, फ़ंक्शन को सीक्रेट ऐक्सेस करने की अनुमति मिली हो:

    Node.js

    const { onRequest } = require('firebase-functions/v2/https');
    
    exports.processPayment = onRequest(
      { secrets: ["SECRET_NAME"] },
      (req, res) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      }
    );

    Python

    import os
    from firebase_functions import https_fn
    
    @https_fn.on_request(secrets=["SECRET_NAME"])
    def process_payment(req):
        myBillingService = initialize_billing(key=os.environ.get('SECRET_NAME'))
        # Process the payment
        ...
    
  4. Cloud Functions डिप्लॉय करें:

    firebase deploy --only functions

    अब इसे किसी भी अन्य एनवायरमेंट वैरिएबल की तरह ऐक्सेस किया जा सकेगा. इसके उलट, अगर कोई दूसरा फ़ंक्शन, सीक्रेट को ऐक्सेस करने की कोशिश करता है, तो उसे कोई वैल्यू नहीं मिलती. ऐसा तब होता है, जब उस फ़ंक्शन में सीक्रेट की जानकारी न दी गई हो:

    Node.js

    exports.anotherEndpoint = onRequest((request, response) => {
      response.send(`The secret API key is ${process.env.SECRET_NAME}`);
      // responds with "The secret API key is undefined" because the `secrets` option is missing
    });
    

    Python

    @https_fn.on_request()
    def another_endpoint(req):
        return https_fn.Response(f"The secret API key is {os.environ.get("SECRET_NAME")}")
        # Responds with "The secret API key is None" because the `secrets` parameter is missing.
    

आपका फ़ंक्शन डिप्लॉय होने के बाद, उसके पास सीक्रेट की वैल्यू का ऐक्सेस होगा. सिर्फ़ उन फ़ंक्शन के पास एनवायरमेंट वैरिएबल के तौर पर सीक्रेट का ऐक्सेस होगा जिनमें secrets विकल्प में सीक्रेट शामिल किया गया है. इससे यह पक्का करने में मदद मिलती है कि सीक्रेट की वैल्यू सिर्फ़ उन जगहों पर उपलब्ध हों जहां उनकी ज़रूरत है. इससे, गलती से सीक्रेट लीक होने का खतरा कम हो जाता है.

सीक्रेट मैनेज करना

अपने सीक्रेट मैनेज करने के लिए, Firebase सीएलआई का इस्तेमाल करें. इस तरीके से सीक्रेट मैनेज करते समय, ध्यान रखें कि सीएलआई में किए गए कुछ बदलावों के लिए, आपको उनसे जुड़े फ़ंक्शन में बदलाव करना और/या उन्हें फिर से डिप्लॉय करना होगा. खास तौर पर:

  • किसी सीक्रेट के लिए नई वैल्यू सेट करने पर, आपको उस सीक्रेट का रेफ़रंस देने वाले सभी फ़ंक्शन को फिर से डिप्लॉय करना होगा, ताकि वे नई वैल्यू को पिक अप कर सकें.
  • अगर कोई सीक्रेट मिटाया जाता है, तो पक्का करें कि डिप्लॉय किए गए किसी भी फ़ंक्शन में उस सीक्रेट का रेफ़रंस न हो. सीक्रेट की उस वैल्यू का इस्तेमाल करने वाले फ़ंक्शन, जिन्हें मिटा दिया गया है, बिना किसी गड़बड़ी के काम नहीं करेंगे.

यहां सीक्रेट मैनेजमेंट के लिए, Firebase सीएलआई के कमांड की खास जानकारी दी गई है:

# Change the value of an existing secret
firebase functions:secrets:set SECRET_NAME

# Set secret from file
firebase functions:secrets:set SECRET_NAME --data-file file.json

# Validate secret value as json
cat file.json | firebase functions:secrets:set SECRET_NAME --format=json

# Pipe from stdin and set secret
cat file.json | firebase functions:secrets:set SECRET_NAME --format=json

# View the value of a secret
functions:secrets:access SECRET_NAME

# Destroy a secret
functions:secrets:destroy SECRET_NAME

# View all secret versions and their state
functions:secrets:get SECRET_NAME

# Automatically clean up all secrets that aren't referenced by any of your functions
functions:secrets:prune

access और destroy कमांड के लिए, किसी खास वर्शन को मैनेज करने के लिए, वर्शन का वैकल्पिक पैरामीटर दिया जा सकता है. उदाहरण के लिए:

functions:secrets:access SECRET_NAME[@VERSION]

इन कार्रवाइयों के बारे में ज़्यादा जानकारी पाने के लिए, सीएलआई की मदद देखने के लिए, कमांड के साथ -h पास करें.

सीक्रेट के लिए बिलिंग का तरीका

Secret Manager में, छह सक्रिय सीक्रेट वर्शन बिना किसी शुल्क के इस्तेमाल किए जा सकते हैं. इसका मतलब है कि Firebase प्रोजेक्ट में, हर महीने छह सीक्रेट बिना किसी शुल्क के इस्तेमाल किए जा सकते हैं.

डिफ़ॉल्ट रूप से, Firebase सीएलआई, इस्तेमाल न किए गए सीक्रेट वर्शन को अपने-आप मिटाने की कोशिश करता है. जैसे, जब सीक्रेट के नए वर्शन के साथ फ़ंक्शन डिप्लॉय किए जाते हैं. इसके अलावा, functions:secrets:destroy और functions:secrets:prune का इस्तेमाल करके, इस्तेमाल न किए गए सीक्रेट को मिटाया जा सकता है.

Secret Manager में, किसी सीक्रेट पर हर महीने 10,000 ऐक्सेस ऑपरेशन बिना किसी शुल्क के किए जा सकते हैं. फ़ंक्शन के इंस्टेंस, हर बार कोल्ड स्टार्ट होने पर, सिर्फ़ उन सीक्रेट को पढ़ते हैं जो उनके secrets विकल्प में तय किए गए हैं. अगर आपके पास ऐसे कई फ़ंक्शन इंस्टेंस हैं जो कई सीक्रेट को पढ़ते हैं, तो आपका प्रोजेक्ट इस सीमा से ज़्यादा हो सकता है. ऐसा होने पर, आपसे हर 10,000 ऐक्सेस ऑपरेशन के लिए 0.03 डॉलर का शुल्क लिया जाएगा.

ज़्यादा जानकारी के लिए, Secret Managerकीमत देखें.

एम्युलेटर की सुविधा

dotenv के साथ एनवायरमेंट कॉन्फ़िगरेशन, स्थानीय Cloud Functions एम्युलेटर के साथ काम करने के लिए डिज़ाइन किया गया है.

स्थानीय Cloud Functions एम्युलेटर का इस्तेमाल करते समय, .env.local फ़ाइल सेट अप करके, अपने प्रोजेक्ट के लिए एनवायरमेंट वैरिएबल को बदला जा सकता है. .env.local का कॉन्टेंट, .env और प्रोजेक्ट के लिए खास .env फ़ाइल के कॉन्टेंट से ज़्यादा प्राथमिकता लेता है.

उदाहरण के लिए, किसी प्रोजेक्ट में ये तीन फ़ाइलें शामिल हो सकती हैं. इनमें डेवलपमेंट और स्थानीय टेस्टिंग के लिए थोड़ी अलग वैल्यू हो सकती हैं:

.env .env.dev .env.local
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Local Humans

स्थानीय कॉन्टेक्स्ट में शुरू होने पर, एम्युलेटर, एनवायरमेंट वैरिएबल को इस तरह लोड करता है:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

Cloud Functions एम्युलेटर में सीक्रेट और क्रेडेंशियल

Cloud Functions एम्युलेटर, संवेदनशील कॉन्फ़िगरेशन की जानकारी सेव करने और उसे ऐक्सेस करने के लिए सीक्रेट के इस्तेमाल की सुविधा देता है . डिफ़ॉल्ट रूप से, एम्युलेटर, ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल का इस्तेमाल करके, आपके प्रोडक्शन सीक्रेट को ऐक्सेस करने की कोशिश करेगा. सीआई एनवायरमेंट जैसी कुछ स्थितियों में, अनुमति से जुड़ी पाबंदियों की वजह से, एम्युलेटर, सीक्रेट की वैल्यू को ऐक्सेस नहीं कर पाएगा.

एनवायरमेंट वैरिएबल के लिए Cloud Functions एम्युलेटर की सुविधा की तरह, फ़ाइल सेट अप करके, सीक्रेट की वैल्यू को बदला जा सकता है..secret.local इससे, स्थानीय तौर पर अपने फ़ंक्शन की जांच करना आसान हो जाता है. खास तौर पर, तब जब आपके पास सीक्रेट की वैल्यू का ऐक्सेस न हो.

रनटाइम कॉन्फ़िगरेशन से माइग्रेट करना

functions.config एपीआई को बंद कर दिया गया है. इसे मार्च 2027 में पूरी तरह से बंद कर दिया जाएगा. इस तारीख के बाद, functions.config के साथ किए जाने वाले डिप्लॉयमेंट काम नहीं करेंगे.

डिप्लॉयमेंट में गड़बड़ियों से बचने के लिए, Firebase सीएलआई का इस्तेमाल करके, अपने कॉन्फ़िगरेशन को Cloud Secret Manager में माइग्रेट करें. हमारा सुझाव है कि अपने कॉन्फ़िगरेशन को माइग्रेट करने के लिए, इस तरीके का इस्तेमाल करें. यह सबसे असरदार और सुरक्षित तरीका है.

  1. सीएलआई से कॉन्फ़िगरेशन एक्सपोर्ट करनाFirebase

    अपने मौजूदा एनवायरमेंट कॉन्फ़िगरेशन को Cloud Secret Manager में नए सीक्रेट में एक्सपोर्ट करने के लिए, config export कमांड का इस्तेमाल करें:

    $ firebase functions:config:export
    i  This command retrieves your Runtime Config values (accessed via functions.config())
       and exports them as a Secret Manager secret.
    
    i  Fetching your existing functions.config() from your project...     Fetched your existing functions.config().
    
    i  Configuration to be exported:
    ⚠  This may contain sensitive data. Do not share this output.
    
    {
       ...
    } What would you like to name the new secret for your configuration? RUNTIME_CONFIG
    
    ✔  Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```
    
  2. सीक्रेट बाइंड करने के लिए, फ़ंक्शन कोड अपडेट करना

    Cloud Secret Manager में नए सीक्रेट में सेव किए गए कॉन्फ़िगरेशन का इस्तेमाल करने के लिए, अपने फ़ंक्शन सोर्स में defineJsonSecret एपीआई का इस्तेमाल करें. साथ ही, पक्का करें कि सीक्रेट, उन सभी फ़ंक्शन से बाइंड हों जिन्हें उनकी ज़रूरत है.

    इससे पहले

    const functions = require("firebase-functions/v1");
    
    exports.myFunction = functions.https.onRequest((req, res) => {
      const apiKey = functions.config().someapi.key;
      // ...
    });
    

    इसके बाद

    const { onRequest } = require("firebase-functions/v2/https");
    const { defineJsonSecret } = require("firebase-functions/params");
    
    const config = defineJsonSecret("RUNTIME_CONFIG");
    
    exports.myFunction = onRequest(
      // Bind secret to your function
      { secrets: [config] },
      (req, res) => {
        // Access secret values via .value()
        const apiKey = config.value().someapi.key;
        // ...
    });
    
  3. फ़ंक्शन डिप्लॉय करना

    बदलावों को लागू करने और सीक्रेट की अनुमतियां बाइंड करने के लिए, अपडेट किए गए फ़ंक्शन डिप्लॉय करें.

    firebase deploy --only functions:<your-function-name>
    

एनवायरमेंट वैरिएबल जो अपने-आप भर जाते हैं

कुछ एनवायरमेंट वैरिएबल ऐसे होते हैं जो फ़ंक्शन के रनटाइम और स्थानीय तौर पर एम्युलेट किए गए फ़ंक्शन में अपने-आप भर जाते हैं. इनमें वे वैरिएबल शामिल हैं जो Google Cloudसे भर जाते हैं, साथ ही Firebase के लिए खास एनवायरमेंट वैरिएबल भी शामिल हैं:

process.env.FIREBASE_CONFIG: Firebase प्रोजेक्ट के कॉन्फ़िगरेशन की यह जानकारी देता है:

{
  databaseURL: 'https://DATABASE_NAME.firebaseio.com',
  storageBucket: 'PROJECT_ID.firebasestorage.app',
  projectId: 'PROJECT_ID'
}

ध्यान दें कि आपके Firebase के मौजूदा कॉन्फ़िगरेशन में मौजूद वैल्यू, आपके प्रोजेक्ट में उपलब्ध कराए गए रिसॉर्स के आधार पर अलग-अलग हो सकती हैं.

जब Firebase Admin SDK को बिना किसी आर्ग्युमेंट के शुरू किया जाता है, तो यह कॉन्फ़िगरेशन अपने-आप लागू हो जाता है. अगर JavaScript में फ़ंक्शन लिखे जा रहे हैं, तो इस तरह शुरू करें:

const admin = require('firebase-admin');
admin.initializeApp();

अगर TypeScript में फ़ंक्शन लिखे जा रहे हैं, तो इस तरह शुरू करें:

import * as functions from 'firebase-functions/v1';
import * as admin from 'firebase-admin';
import 'firebase-functions/v1';
admin.initializeApp();

अगर आपको सेवा खाते के क्रेडेंशियल का इस्तेमाल करके, डिफ़ॉल्ट प्रोजेक्ट कॉन्फ़िगरेशन के साथ Admin SDK को शुरू करना है, तो क्रेडेंशियल को किसी फ़ाइल से लोड किया जा सकता है और उन्हें FIREBASE_CONFIG में इस तरह जोड़ा जा सकता है:

serviceAccount = require('./serviceAccount.json');

const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);