Calling a Cloud Function from another Cloud Function

前端 未结 4 2082
时光取名叫无心
时光取名叫无心 2020-11-27 18:58

I am using a Cloud Function to call another Cloud Function on the free spark tier.

Is there a special way to call another Cloud Function? Or do you just use a standa

相关标签:
4条回答
  • 2020-11-27 19:15

    You don't need to go through the trouble of invoking some shared functionality via a whole new HTTPS call. You can simply abstract away the common bits of code into a regular javascript function that gets called by either one. For example, you could modify the template helloWorld function like this:

    var functions = require('firebase-functions');
    
    exports.helloWorld = functions.https.onRequest((request, response) => {
      common(response)
    })
    
    exports.helloWorld2 = functions.https.onRequest((request, response) => {
      common(response)
    })
    
    function common(response) {
      response.send("Hello from a regular old function!");
    }
    

    These two functions will do exactly the same thing, but with different endpoints.

    0 讨论(0)
  • 2020-11-27 19:15

    To answer the question, you can do an https request to call another cloud function:

    export const callCloudFunction = async (functionName: string, data: {} = {}) => {
        let url = `https://us-central1-${config.firebase.projectId}.cloudfunctions.net/${functionName}`
        await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ data }),
        })
    }
    

    (Note we are using the npm package 'node-fetch' as our fetch implementation.)

    And then simply call it:

    callCloudFunction('search', { query: 'yo' })
    

    There are legitimate reasons to do this. We used this to ping our search cloud function every minute and keep it running. This greatly lowers response latency for a few dollars a year.

    0 讨论(0)
  • 2020-11-27 19:20

    It's possible to invoke another Google Cloud Function over HTTP by including an authorization token. It requires a primary HTTP request to calculate the token, which you then use when you call the actual Google Cloud Function that you want to run.

    https://cloud.google.com/functions/docs/securing/authenticating#function-to-function

    const {get} = require('axios');
    
    // TODO(developer): set these values
    const REGION = 'us-central1';
    const PROJECT_ID = 'my-project-id';
    const RECEIVING_FUNCTION = 'myFunction';
    
    // Constants for setting up metadata server request
    // See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
    const functionURL = `https://${REGION}-${PROJECT_ID}.cloudfunctions.net/${RECEIVING_FUNCTION}`;
    const metadataServerURL =
      'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
    const tokenUrl = metadataServerURL + functionURL;
    
    exports.callingFunction = async (req, res) => {
      // Fetch the token
      const tokenResponse = await get(tokenUrl, {
        headers: {
          'Metadata-Flavor': 'Google',
        },
      });
      const token = tokenResponse.data;
    
      // Provide the token in the request to the receiving function
      try {
        const functionResponse = await get(functionURL, {
          headers: {Authorization: `bearer ${token}`},
        });
        res.status(200).send(functionResponse.data);
      } catch (err) {
        console.error(err);
        res.status(500).send('An error occurred! See logs for more details.');
      }
    };
    
    0 讨论(0)
  • 2020-11-27 19:25

    Despite of the question tag and other answers concern the javascript I want to share the python example as it reflects the title and also authentification aspect mentioned in the question.

    Google Cloud Function provide REST API interface what incluse call method that can be used in another Cloud Function. Although the documentation mention using Google-provided client libraries there is still non one for Cloud Function on Python.

    And instead you need to use general Google API Client Libraries. [This is the python one].3

    Probably, the main difficulties while using this approach is an understanding of authentification process. Generally you need provide two things to build a client service: credentials ans scopes.

    The simpliest way to get credentials is relay on Application Default Credentials (ADC) library. The rigth documentation about that are:

    1. https://cloud.google.com/docs/authentication/production
    2. https://github.com/googleapis/google-api-python-client/blob/master/docs/auth.md

    The place where to get scopes is the each REST API function documentation page. Like, OAuth scope: https://www.googleapis.com/auth/cloud-platform

    The complete code example of calling 'hello-world' clound fucntion is below. Before run:

    1. Create default Cloud Function on GCP in your project.
    • Keep and notice the default service account to use
    • Keep the default body.
    1. Notice the project_id, function name, location where you deploy function.
    2. If you will call function outside Cloud Function environment (locally for instance) setup the environment variable GOOGLE_APPLICATION_CREDENTIALS according the doc mentioned above
    3. If you will call actualy from another Cloud Function you don't need to configure credentials at all.
    from googleapiclient.discovery import build
    from googleapiclient.discovery_cache.base import Cache
    import google.auth
    
    import pprint as pp
    
    def get_cloud_function_api_service():
        class MemoryCache(Cache):
            _CACHE = {}
    
            def get(self, url):
                return MemoryCache._CACHE.get(url)
    
            def set(self, url, content):
                MemoryCache._CACHE[url] = content
    
        scopes = ['https://www.googleapis.com/auth/cloud-platform']
    
        # If the environment variable GOOGLE_APPLICATION_CREDENTIALS is set,
        # ADC uses the service account file that the variable points to.
        #
        # If the environment variable GOOGLE_APPLICATION_CREDENTIALS isn't set,
        # ADC uses the default service account that Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run,
        # and Cloud Functions provide
        #
        # see more on https://cloud.google.com/docs/authentication/production
        credentials, project_id = google.auth.default(scopes)
    
        service = build('cloudfunctions', 'v1', credentials=credentials, cache=MemoryCache())
        return service
    
    
    google_api_service = get_cloud_function_api_service()
    name = 'projects/{project_id}/locations/us-central1/functions/function-1'
    body = {
        'data': '{ "message": "It is awesome, you are develop on Stack Overflow language!"}' # json passed as a string
    }
    result_call = google_api_service.projects().locations().functions().call(name=name, body=body).execute()
    pp.pprint(result_call)
    # expected out out is:
    # {'executionId': '3h4c8cb1kwe2', 'result': 'It is awesome, you are develop on Stack Overflow language!'}
    
    
    0 讨论(0)
提交回复
热议问题