programing

다른 클라우드 함수에서 클라우드 함수 호출

lastmoon 2023. 6. 21. 22:53
반응형

다른 클라우드 함수에서 클라우드 함수 호출

클라우드 기능을 사용하여 무료 스파크 계층의 다른 클라우드 기능을 호출하고 있습니다.

다른 클라우드 기능을 호출하는 특별한 방법이 있습니까?아니면 그냥 표준 http 요청을 사용합니까?

다른 함수를 직접 호출해 보았습니다.

exports.purchaseTicket = functions.https.onRequest((req, res) => {    
  fetch('https://us-central1-functions-****.cloudfunctions.net/validate')
    .then(response => response.json())
    .then(json => res.status(201).json(json))
})

하지만 나는 오류를 이해합니다.

FetchError: https://us-central1-beta-**.cloudfunctions.net/validate 에 대한 요청이 실패했습니다. 이유: getaddrinfo ENOTFOUND us-central1-beta-***.cloudfunctions.net us-central1-beta-***

파이어베이스가 구글 소유임에도 불구하고 연결을 차단하는 것처럼 들립니다. 따라서 잠금 상태가 되면 안 됩니다.

Spark 요금제는 Google 소유 서비스에 대한 아웃바운드 네트워크 요청만 허용합니다.

클라우드 기능을 사용하여 다른 클라우드 기능을 호출하려면 어떻게 해야 합니까?

완전히 새로운 HTTPS 호출을 통해 일부 공유 기능을 호출하는 번거로움을 겪지 않아도 됩니다.일반적인 코드 조각을 일반 자바스크립트 함수로 추상화하여 둘 중 하나로 호출할 수 있습니다.예를 들어 다음과 같이 템플릿 helloWorld 함수를 수정할 수 있습니다.

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!");
}

이 두 기능은 엔드포인트가 다르지만 정확히 동일한 작업을 수행합니다.

질문에 답하려면 https 요청을 수행하여 다른 클라우드 함수를 호출할 수 있습니다.

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 }),
    })
}

npm 패키지 'node-fetch'를 fetch 구현으로 사용하고 있습니다.

그런 다음 간단히 다음과 같이 부릅니다.

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

이렇게 하는 데는 정당한 이유가 있습니다.우리는 이것을 사용하여 검색 클라우드 기능을 매 분마다 ping하고 실행을 유지했습니다.이를 통해 연간 몇 달러의 응답 대기 시간을 크게 줄일 수 있습니다.

인증 토큰을 포함하여 HTTP를 통해 다른 Google Cloud Function을 호출할 수 있습니다.토큰을 계산하려면 기본 HTTP 요청이 필요하며, 실행할 실제 Google Cloud Function을 호출할 때 이 요청을 사용합니다.

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.google.internal/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.');
  }
};

2021년 10월 업데이트:로컬 개발 환경에서 이 작업을 수행할 필요가 없습니다. 이 작업을 명확히 해 주셔서 감사합니다.

질문 태그와 다른 답변에도 불구하고 저는 javascript와 관련하여 제목과 질문에 언급된 인증 측면을 반영하기 때문에 python 예제를 공유하고 싶습니다.

Google Cloud Function은 다른 Cloud Function에서 사용할 수 있는 호출 방법을 포함하는 REST API 인터페이스를 제공합니다.설명서에 Google에서 제공하는 클라이언트 라이브러리를 사용하는 것이 언급되어 있지만 Python에서는 Cloud Function에 대한 라이브러리가 아직 없습니다.

대신 일반 Google API 클라이언트 라이브러리를 사용해야 합니다.[이것은 비단뱀입니다.]3

이 방법을 사용할 때 가장 큰 어려움은 인증 프로세스를 이해하는 것입니다.일반적으로 클라이언트 서비스를 구축하려면 자격 증명 및 범위라는 두 가지를 제공해야 합니다.

자격 증명을 가져오는 가장 간단한 방법은 ADC(Application Default Credentials) 라이브러리의 릴레이입니다.이에 대한 올바른 설명서는 다음과 같습니다.

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

스코프를 가져오는 위치는 각 REST API 함수 설명서 페이지입니다.예를 들어, OAuth 범위: https://www.googleapis.com/auth/cloud-platform

'hello-world' 클라우드 함수를 호출하는 완전한 코드 예제는 아래와 같습니다.실행 전:

  1. 프로젝트의 GCP에 기본 클라우드 기능을 만듭니다.
  • 사용할 기본 서비스 계정을 유지하고 확인
  • 기본 본문을 유지합니다.
  1. project_id, 함수 이름, 함수를 배포하는 위치를 확인합니다.
  2. Cloud Function 환경 외부(예: 로컬)에서 function을 호출할 경우 위에 언급된 문서에 따라 환경 변수 GOOGLE_APPLICATION_CREDIES를 설정합니다.
  3. 실제로 다른 클라우드 기능에서 호출하는 경우 자격 증명을 구성할 필요가 전혀 없습니다.
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!'}

이 제안들은 더 이상 효과가 없는 것 같습니다.

저는 이를 위해 httpsCallable을 사용하여 클라이언트 측에서 전화를 걸어 요청을 우체부로 가져왔습니다.https://firebase.google.com/docs/functions/callable-reference 에 대한 다른 링크도 도움이 되었습니다.하지만 정보를 어디서 구할 수 있는지를 결정하는 데는 시간이 좀 걸렸습니다.

설명과 몇 가지 예시가 필요하기 때문에 저는 여기에 모든 것을 적었습니다.

https://www.tiftonpartners.com/post/call-google-cloud-function-from-another-cloud-function

다음은 'url'이 만료될 수 있는 인라인 버전입니다.

이 '해야 한다'는 것은 테스트된 것이 아니라 제가 작성하고 제 애플리케이션을 테스트한 것을 기반으로 합니다.

module.exports = function(name,context) {
    const {protocol,headers} = context.rawRequest;
    const host = headers['x-forwardedfor-host'] || headers.host;
    // there will be two different paths for
    // production and development
    const url = `${protocol}://${host}/${name}`;
    const method = 'post';    
    const auth = headers.authorization;
    
    return (...rest) => {
        const data = JSON.stringify({data:rest});
        const config = {
            method, url, data,
            headers: {
               'Content-Type': 'application/json',
               'Authorization': auth,
               'Connection': 'keep-alive',
               'Pragma': 'no-cache,
               'Cache-control': 'no-cache',
            }
        };
        try {
            const {data:{result}} = await axios(config);
            return result;        
        } catch(e) {
            throw e;
        }
    }
}

이 함수를 이렇게 부릅니다.

const crud = httpsCallable('crud',context);
return await crud('read',...data);

구글 클라우드 진입점에서 얻을 수 있는 컨텍스트는 가장 중요한 부분이며, 클라우드 기능에 대한 후속 호출에 필요한 JWT 토큰이 포함되어 있습니다(내 예에서는 crud).

다른 httpsCallable 끝점을 정의하려면 다음과 같이 내보내기 문을 작성합니다.

exports.crud = functions.https.onCall(async (data, context) => {})

마법처럼 작동해야 합니다.

이게 도움이 되길 바랍니다.

나는 두 가지 방법의 조합이 가장 효과적이라는 것을 발견했습니다.

const anprURL = `https://${REGION}-${PROJECT_ID}.cloudfunctions.net/${RECEIVING_FUNCTION}`;
const metadataServerURL =
  'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=';
const tokenUrl = metadataServerURL + anprURL;

// Fetch the token
const tokenResponse = await fetch(tokenUrl, {
    method: "GET"
    headers: {
      'Metadata-Flavor': 'Google',
    },
});

const token = await tokenResponse.text();

const functionResponse = await fetch(anprURL, {
    method: 'POST',
    headers: {
        "Authorization": `bearer ${token}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({"imageUrl": url}),
});

// Convert the response to text
const responseText = await functionResponse.text();

// Convert from text to json
const reponseJson = JSON.parse(responseText);

Shhea Hunter Belsky의 답변을 연장하여 Google의 메타데이터 서버로 인증 토큰을 가져오기 위한 호출이 로컬 컴퓨터에서 작동하지 않음을 알려드립니다.

부터fetch노드에서 쉽게 사용할 수 없습니다.JS와 제 프로젝트는 이미 사용하고 있었습니다.axios도서관, 나는 이렇게 했습니다.

const url = `https://${REGION}-${PROJECT_ID}.cloudfunctions.net/${FUNCTION_NAME}`;
const headers = {
  'Content-Type': 'application/json',
};
const response = await axios.post(url, { data: YOUR_DATA }, { headers });

언급URL : https://stackoverflow.com/questions/42784000/calling-a-cloud-function-from-another-cloud-function

반응형