Escribe funciones de Cloud Run

En esta página, se describe cómo escribir funciones de Cloud Run controladas por eventos y HTTP con Functions Framework.

Descripción general de Functions Framework

Cuando escribas el código fuente de las funciones, debes usar Functions Framework, una biblioteca de código abierto para escribir Cloud Run Functions. Con Functions Framework, puedes escribir funciones ligeras que se ejecutan en Cloud Run y en otros entornos, como tu máquina de desarrollo local y los entornos basados en Knative.

Functions Framework te permite hacer lo siguiente:

  • Invoca una función de Cloud Run en respuesta a una solicitud.
  • Deserializar de forma automática los eventos conforme a la especificación de CloudEvents, una especificación estándar de la industria para describir los datos de eventos de manera común
  • Inicia un servidor de desarrollo local para realizar pruebas.

Functions Framework proporciona una interfaz para compilar servicios modulares. Para usar Functions Framework en tu código fuente, especifica lo siguiente:

Punto de entrada de la función

El código fuente debe definir un punto de entrada de la función, que es el código que se ejecuta cuando Cloud Run invoca la función. Especificas este punto de entrada cuando implementas la función.

La forma en que defines el punto de entrada depende del entorno de ejecución del lenguaje que usas. Algunos lenguajes usan una función como punto de entrada, mientras que otros usan una clase.

Tipo de firma

Cuando escribes el código fuente de una función con Functions Framework, debes especificar uno de los dos tipos de firma:

  • Funciones HTTP: Registra una función de controlador HTTP. Usa una función HTTP cuando tu función necesite un extremo de URL y deba responder a solicitudes HTTP, como para webhooks.
  • Funciones controladas por eventos, también conocidas como funciones de CloudEvents: Registra una función de controlador de CloudEvents. Usa una función controlada por eventos cuando la función se active directamente en respuesta a eventos dentro de tu proyecto Google Cloud , como mensajes en un tema de Pub/Sub o cambios en un bucket de Cloud Storage.

Estructura de directorios del código fuente

Functions Framework es compatible con varios lenguajes de programación. El entorno de ejecución de lenguaje que elijas y el tipo de función que desees escribir determinarán cómo estructurar el código e implementar tu función.

Para que Cloud Run localice la definición de tu función, cada entorno de ejecución de lenguaje tiene requisitos para estructurar tu código fuente.

Node.js

A continuación, se muestra la estructura básica de directorios para las funciones de Node.js:

.
├── index.js
└── package.json

De forma predeterminada, Cloud Run intenta cargar el código fuente desde un archivo llamado index.js en la raíz del directorio de tu función. Para especificar un archivo de origen principal diferente, usa el campo main en el archivo package.json.

Tu archivo package.json también debe incluir Functions Framework para Node.js como una dependencia:

{
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.0.0"
  },
  "type": "module"
}

El código de tu archivo principal debe definir el punto de entrada de la función y puede importar otros códigos y módulos de Node.js. El archivo principal también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Consulta la descripción general del entorno de ejecución de Node.js y Functions Framework para Node.js para obtener más detalles.

Python

A continuación, se muestra la estructura básica de directorios para las funciones de Python:

.
├── main.py
└── requirements.txt

Cloud Run carga el código fuente de un archivo llamado main.py en la raíz del directorio de tu función. Debes asignar el nombre main.py a tu archivo principal.

El archivo requirements.txt debe incluir Functions Framework para Python como una dependencia:

functions-framework==3.*

El código de tu archivo main.py debe definir el punto de entrada de la función y puede importar otro código y dependencias externas con normalidad. El archivo main.py también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Consulta la Descripción general del entorno de ejecución de Python y el framework de Functions para Python para obtener más detalles.

Go

La estructura básica de directorios para las funciones de Go es la siguiente:

.
├── myfunction.go
└── go.mod

Tu función debe estar en un paquete de Go en la raíz de tu proyecto. El paquete y sus archivos de origen pueden tener cualquier nombre, excepto que la función no puede estar en package main. Si necesitas un paquete main, por ejemplo, para realizar pruebas locales, puedes crear uno en un subdirectorio:

.
├── myfunction.go
├── go.mod
└── cmd/
  └── main.go

El archivo go.mod debe incluir Functions Framework para Go como una dependencia:

module example.com/my-module

require (
  github.com/GoogleCloudPlatform/functions-framework-go v1.5.2
)

El código de tu paquete raíz debe definir el punto de entrada de tu función y puede importar otro código de subpaquetes y dependencias con normalidad. El paquete también puede definir varios puntos de entrada de funciones que pueden implementarse por separado.

Consulta la descripción general del entorno de ejecución de Go y el Functions Framework para Go para obtener más detalles.

Java

La estructura de directorios básica de las funciones de Java es la siguiente:

.
├── pom.xml
└── src/
  └── main/
      └── java/
          └── MyFunction.java

Los archivos de origen de Java deben estar en el directorio src/main/java/ y pueden tener cualquier nombre. Si tus archivos de origen declaran un paquete, agrega un directorio adicional en src/main/java con el nombre del paquete:

.
├── pom.xml
└── src/
  └── main/
      └── java/
          └── mypackage/
              └── MyFunction.java

Recomendamos colocar pruebas asociadas en un subdirectorio src/test/java/.

El archivo pom.xml debe incluir Functions Framework para Java como una dependencia:

...
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.0.4</version>
    </dependency>
...

El código de tus archivos de origen debe definir el punto de entrada de la función y puede importar otro código y dependencias externas con normalidad. Los archivos de origen también pueden definir varios puntos de entrada de funciones que pueden implementarse por separado.

Consulta la descripción general del entorno de ejecución de Java y el Functions Framework para Java para obtener más detalles.

.NET

La estructura básica de directorios para las funciones de .NET es la siguiente:

.
├── MyFunction.cs
└── MyProject.csproj

Puedes estructurar los proyectos como lo harías con cualquier otro código fuente .NET. Los archivos de origen pueden tener cualquier nombre.

El archivo de tu proyecto debe incluir Functions Framework para .NET como una dependencia:

...
    <PackageReference Include="Google.Cloud.Functions.Hosting" Version="1.0.0" />
...

El código de tus archivos de origen debe definir el punto de entrada de la función y puede importar otro código y dependencias externas con normalidad. Los archivos de origen también pueden definir varios puntos de entrada de funciones que pueden implementarse por separado.

Para obtener más detalles, consulta la descripción general del entorno de ejecución de.NET y el Functions Framework para .NET.

Ruby

La estructura de directorios básica de las funciones de Ruby es la siguiente:

.
├── app.rb
├── Gemfile
└── Gemfile.lock

Cloud Run carga el código fuente de un archivo llamado app.rb en la raíz del directorio de tu función. Tu archivo principal debe llamarse app.rb.

El archivo Gemfile debe incluir Functions Framework para Ruby como una dependencia:

source "https://rubygems.org"
gem "functions_framework", "~> 1.0"

El código de tu archivo app.rb debe definir el punto de entrada de la función y puede importar otro código y dependencias externas con normalidad. El archivo app.rb también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Para obtener más detalles, consulta la descripción general del entorno de ejecución de Ruby y el framework de Functions para Ruby.

PHP

La estructura básica de directorios para las funciones de PHP es la siguiente:

.
├── index.php
└── composer.json

Cloud Run carga el código fuente de un archivo llamado index.php en la raíz del directorio de tu función. Debes asignar el nombre index.php a tu archivo principal.

El archivo composer.json debe incluir Functions Framework para PHP como una dependencia:

{
  "require": {
    "google/cloud-functions-framework": "^1.1"
  }
}

El código de tu archivo index.php debe definir el punto de entrada de la función y puede importar otro código y dependencias externas con normalidad. El archivo index.php también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Consulta la Descripción general del entorno de ejecución de PHP y el Functions Framework para PHP para obtener más detalles.

Si agrupas varias funciones en un solo proyecto, ten en cuenta que cada función puede terminar compartiendo el mismo conjunto de dependencias. Sin embargo, es posible que algunas de las funciones no necesiten todas las dependencias.

Siempre que sea posible, recomendamos dividir las bases de código multifunción grandes y colocar cada función en su propio directorio de nivel superior, como se muestra en los ejemplos anteriores, con sus propios archivos de configuración de origen y de proyecto. Este enfoque minimiza la cantidad de dependencias necesarias para una función específica, lo que, a su vez, reduce la cantidad de memoria que necesita tu función.

Escribe funciones HTTP

Escribe una función de HTTP cuando quieras invocar una función a través de una solicitud HTTP(S). Para permitir la semántica de HTTP, usa el Function Framework y especifica la firma de la función de HTTP para aceptar argumentos específicos de HTTP.

En el siguiente ejemplo, se muestra el archivo de origen de una función básica HTTP para cada entorno de ejecución. Para ver un ejemplo completo en funcionamiento, consulta Implementa una función de Cloud Run con Google Cloud CLI. Para obtener más información sobre dónde ubicar el código fuente, consulta Estructura del directorio del código fuente.

Node.js

Módulo de ES

  import { http } from '@google-cloud/functions-framework';
  http('myHttpFunction', (req, res) => {
    // Your code here

    // Send an HTTP response
    res.send('OK');
  });

Agrega las siguientes dependencias, incluido "type": "module" en tu archivo package.json:

  {
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0"
    },
    "type": "module"
  }

Módulo CommonJS

  const functions = require('@google-cloud/functions-framework');

  // Register an HTTP function with the Functions Framework
  functions.http('myHttpFunction', (req, res) => {
    // Your code here

    // Send an HTTP response
    res.send('OK');
  });

Agrega las siguientes dependencias en tu archivo package.json:

  {
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0"
    }
  }

En Node.js, registra una función de controlador HTTP con Functions Framework para Node.js. Tu función de controlador HTTP debe ser una función de middleware exprés que acepte los argumentos de solicitud y respuesta y que envíe una respuesta HTTP.

Cloud Run analiza el cuerpo de la solicitud de manera automática según el encabezado Content-Type de la solicitud con body-parser, para que puedas acceder a los objetos req.body y req.rawBody en tu controlador HTTP.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es myHttpFunction.

Python

import functions_framework

# Register an HTTP function with the Functions Framework
@functions_framework.http
def my_http_function(request):
  # Your code here

  # Return an HTTP response
  return 'OK'

En Python, registras una función de controlador HTTP con Functions Framework para Python. Tu función de controlador HTTP debe aceptar un objeto de solicitud de Flask como un argumento y mostrar un valor que Flask puede convertir en un objeto de respuesta HTTP.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es my_http_function.

Go

package myhttpfunction

import (
    "fmt"
    "net/http"

    "github.com/GoogleCloudPlatform/functions-framework-go/functions"
)

func init() {
    // Register an HTTP function with the Functions Framework
    functions.HTTP("MyHTTPFunction", myHTTPFunction)
}

// Function myHTTPFunction is an HTTP handler
func myHTTPFunction(w http.ResponseWriter, r *http.Request) {
    // Your code here

    // Send an HTTP response
    fmt.Fprintln(w, "OK")
}

En Go, registra una función de controlador HTTP con Functions Framework para Go en tu función init(). La función del controlador HTTP debe usar la interfaz http.HandlerFunc estándar para enviar una respuesta HTTP.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es MyHTTPFunction.

La función de tu controlador HTTP debe implementar la interfaz http.HandlerFunc estándar. Acepta una interfaz http.ResponseWriter que tu función usa para crear una respuesta a la solicitud, así como un puntero a una estructura http.Request que contiene los detalles de la solicitud HTTP entrante.

Java

package myhttpfunction;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;

// Define a class that implements the HttpFunction interface
public class MyHttpFunction implements HttpFunction {
  // Implement the service() method to handle HTTP requests
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    // Your code here

    // Send an HTTP response
    response.getWriter().write("OK");
  }
}

En Java, debes usar la API de Functions Framework para Java a fin de implementar una clase de controlador HTTP con la interfaz HttpFunction. El método service() debe enviar una respuesta HTTP.

El punto de entrada de la función es el nombre completamente calificado de la clase del controlador HTTP, incluido el nombre del paquete. En este ejemplo, el punto de entrada es myhttpfunction.MyHttpFunction.

Tu método service recibe un objeto HttpRequest que describe la solicitud HTTP entrante, así como un objeto HttpResponse que se propaga en tu función con un mensaje de respuesta.

.NET

using Google.Cloud.Functions.Framework;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

namespace MyProject
{
    // Define a class that implements the IHttpFunction interface
    public class MyHttpFunction : IHttpFunction
    {
        // Implement the HandleAsync() method to handle HTTP requests
        public async Task HandleAsync(HttpContext context)
        {
            // Your code here

            // Send an HTTP response
            await context.Response.WriteAsync("OK");
        }
    }
}

En los entornos de ejecución de .NET, usas Functions Framework para .NET a fin de implementar una clase de controlador HTTP con la interfaz de IHttpFunction. El método HandleAsync() acepta un objeto HttpContext de ASP.NET estándar como argumento y debe enviar una respuesta HTTP.

El punto de entrada de la función es el nombre completamente calificado de la clase de controlador HTTP, incluido el espacio de nombres. En este ejemplo, el punto de entrada es MyProject.MyHttpFunction.

Ruby

require "functions_framework"

# Register an HTTP function with the Functions Framework
FunctionsFramework.http "my_http_function" do |request|
  # Your code here

  # Return an HTTP response
  "OK"
end

En Ruby, registras una función de controlador HTTP con Functions Framework para Ruby. La función de controlador HTTP debe aceptar un objeto de solicitud de Rack como argumento y mostrar un valor que se puede usar como respuesta HTTP.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es my_http_function.

PHP

<?php

use Google\CloudFunctions\FunctionsFramework;
use Psr\Http\Message\ServerRequestInterface;

// Register an HTTP function with the Functions Framework
FunctionsFramework::http('myHttpFunction', 'myHttpHandler');

// Define your HTTP handler
function myHttpHandler(ServerRequestInterface $request): string
{
    // Your code here

    // Return an HTTP response
    return 'OK';
}

En PHP, registras una función de controlador HTTP con Functions Framework para PHP. Tu función de controlador HTTP debe aceptar un argumento que implemente la interfaz ServerRequestInterface de PSR-7 y debe mostrar una respuesta HTTP como una cadena o un objeto que implemente la interfaz ResponseInterface de PSR-7.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es myHttpFunction.

Solicitudes y respuestas HTTP

Cuando registras una función de controlador HTTP con Functions Framework, tu controlador HTTP puede inspeccionar el método de solicitud y realizar diferentes acciones en función del método.

Cuando configuras un proveedor de eventos para que envíe solicitudes HTTP a tu función de Cloud Run, esta envía una respuesta HTTP. Si la función crea tareas en segundo plano (como subprocesos, futuros, objetos Promise de JavaScript, devoluciones de llamada o procesos del sistema), debes finalizar o resolver estas tareas antes de enviar una respuesta HTTP. Es posible que no se completen las tareas que no se finalicen antes de enviar la respuesta HTTP, lo que puede causar un comportamiento indefinido.

Cómo controlar CORS

El uso compartido de recursos entre dominios (CORS) es una forma de permitir que las aplicaciones que se ejecutan en un dominio accedan a los recursos de otro dominio. Por ejemplo, es posible que debas permitir que el dominio realice solicitudes al dominio de Cloud Run Functions para acceder a la función.

Para permitir solicitudes de origen cruzado a tu función, configura el encabezado Access-Control-Allow-Origin según corresponda en la respuesta HTTP. Para las solicitudes de origen cruzado con solicitud preliminar, debes responder a la solicitud OPTIONS preliminar con un código de respuesta 204 y encabezados adicionales.

Node.js

const functions = require('@google-cloud/functions-framework');

/**
 * HTTP function that supports CORS requests.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
functions.http('corsEnabledFunction', (req, res) => {
  // Set CORS headers for preflight requests
  // Allows GETs from any origin with the Content-Type header
  // and caches preflight response for 3600s

  res.set('Access-Control-Allow-Origin', '*');

  if (req.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    res.set('Access-Control-Allow-Methods', 'GET');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
  } else {
    res.send('Hello World!');
  }
});

Python

import functions_framework

@functions_framework.http
def cors_enabled_function(request):
    # For more information about CORS and CORS preflight requests, see:
    # https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

    # Set CORS headers for the preflight request
    if request.method == "OPTIONS":
        # Allows GET requests from any origin with the Content-Type
        # header and caches preflight response for an 3600s
        headers = {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "GET",
            "Access-Control-Allow-Headers": "Content-Type",
            "Access-Control-Max-Age": "3600",
        }

        return ("", 204, headers)

    # Set CORS headers for the main request
    headers = {"Access-Control-Allow-Origin": "*"}

    return ("Hello World!", 200, headers)

Go


// Package http provides a set of HTTP Cloud Functions samples.
package http

import (
	"fmt"
	"net/http"

	"github.com/GoogleCloudPlatform/functions-framework-go/functions"
)

// CORSEnabledFunction is an example of setting CORS headers.
// For more information about CORS and CORS preflight requests, see
// https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request.
func CORSEnabledFunction(w http.ResponseWriter, r *http.Request) {
	// Set CORS headers for the preflight request
	if r.Method == http.MethodOptions {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "POST")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
		w.Header().Set("Access-Control-Max-Age", "3600")
		w.WriteHeader(http.StatusNoContent)
		return
	}
	// Set CORS headers for the main request.
	w.Header().Set("Access-Control-Allow-Origin", "*")
	fmt.Fprint(w, "Hello, World!")
}

func init() {
	functions.HTTP("CORSEnabledFunction", CORSEnabledFunction)
}

Java


import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.HttpURLConnection;

public class CorsEnabled implements HttpFunction {
  // corsEnabled is an example of setting CORS headers.
  // For more information about CORS and CORS preflight requests, see
  // https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request.
  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException {
    // Set CORS headers
    //   Allows GETs from any origin with the Content-Type
    //   header and caches preflight response for 3600s
    response.appendHeader("Access-Control-Allow-Origin", "*");

    if ("OPTIONS".equals(request.getMethod())) {
      response.appendHeader("Access-Control-Allow-Methods", "GET");
      response.appendHeader("Access-Control-Allow-Headers", "Content-Type");
      response.appendHeader("Access-Control-Max-Age", "3600");
      response.setStatusCode(HttpURLConnection.HTTP_NO_CONTENT);
      return;
    }

    // Handle the main request.
    BufferedWriter writer = response.getWriter();
    writer.write("CORS headers set successfully!");
  }
}

.NET

using Google.Cloud.Functions.Framework;
using Microsoft.AspNetCore.Http;
using System.Net;
using System.Threading.Tasks;

namespace Cors;

// For more information about CORS and CORS preflight requests, see
// https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request.
public class Function : IHttpFunction
{
    public async Task HandleAsync(HttpContext context)
    {
        HttpRequest request = context.Request;
        HttpResponse response = context.Response;

        // Set CORS headers
        //   Allows GETs from any origin with the Content-Type
        //   header and caches preflight response for 3600s

        response.Headers.Append("Access-Control-Allow-Origin", "*");
        if (HttpMethods.IsOptions(request.Method))
        {
            response.Headers.Append("Access-Control-Allow-Methods", "GET");
            response.Headers.Append("Access-Control-Allow-Headers", "Content-Type");
            response.Headers.Append("Access-Control-Max-Age", "3600");
            response.StatusCode = (int) HttpStatusCode.NoContent;
            return;
        }

        await response.WriteAsync("CORS headers set successfully!", context.RequestAborted);
    }
}

Ruby

FunctionsFramework.http "cors_enabled_function" do |request|
  # For more information about CORS and CORS preflight requests, see
  # https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
  # for more information.

  # Set CORS headers for the preflight request
  if request.options?
    # Allows GET requests from any origin with the Content-Type
    # header and caches preflight response for an 3600s
    headers = {
      "Access-Control-Allow-Origin"  => "*",
      "Access-Control-Allow-Methods" => "GET",
      "Access-Control-Allow-Headers" => "Content-Type",
      "Access-Control-Max-Age"       => "3600"
    }
    [204, headers, []]
  else
    # Set CORS headers for the main request
    headers = {
      "Access-Control-Allow-Origin" => "*"
    }

    [200, headers, ["Hello World!"]]
  end
end

PHP


use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use GuzzleHttp\Psr7\Response;

function corsEnabledFunction(ServerRequestInterface $request): ResponseInterface
{
    // Set CORS headers for preflight requests
    // Allows GETs from any origin with the Content-Type header
    // and caches preflight response for 3600s
    $headers = ['Access-Control-Allow-Origin' => '*'];

    if ($request->getMethod() === 'OPTIONS') {
        // Send response to OPTIONS requests
        $headers = array_merge($headers, [
            'Access-Control-Allow-Methods' => 'GET',
            'Access-Control-Allow-Headers' => 'Content-Type',
            'Access-Control-Max-Age' => '3600'
        ]);
        return new Response(204, $headers, '');
    } else {
        return new Response(200, $headers, 'Hello World!');
    }
}

Si CORS no está configurado correctamente, es posible que veas errores como el siguiente:

XMLHttpRequest cannot load https://YOUR_FUNCTION_URL.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'https://YOUR_DOMAIN' is therefore not allowed access.

Limitaciones de CORS

Para las solicitudes preliminares de origen cruzado, las solicitudes OPTIONS preliminares se envían sin un encabezado de Authorization, por lo que se rechazarán en todas las funciones de HTTP que requieran autenticación. Como las solicitudes de comprobación previa fallan, la solicitud principal también lo hará. Para evitar esta limitación, usa una de las siguientes opciones:

Escribe funciones controladas por eventos

Escribe una función controlada por eventos cuando quieras que una función se active directamente en respuesta a eventos dentro de tu proyecto de Google Cloud , como mensajes en un tema de Pub/Sub o cambios en un bucket de Cloud Storage.

Las funciones basadas en eventos se basan en CloudEvents, una especificación estándar de la industria para describir los datos de eventos de manera común. Puedes obtener más información sobre la especificación de CloudEvents en el repositorio de GitHub de CloudEvents. El proyecto de CloudEvents también proporciona un conjunto de SDK de CloudEvents para ayudarte a trabajar con objetos de CloudEvents en tu código.

En el siguiente ejemplo, se muestra el archivo de origen de una función controlada por eventos para cada entorno de ejecución. Consulta la Estructura del directorio del código fuente para obtener información sobre dónde ubicar el código fuente.

Node.js

Módulo de ES

  import { cloudEvent } from "@google-cloud/functions-framework";
  cloudEvent('myCloudEventFunction', cloudEvent => {
    // Your code here
    // Access the CloudEvent data payload using cloudEvent.data
  });

Agrega las siguientes dependencias, incluido "type": "module" en tu archivo package.json:

  {
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0"
    },
    "type": "module"
  }

Módulo CommonJS

const functions = require('@google-cloud/functions-framework');

// Register a CloudEvent function with the Functions Framework
functions.cloudEvent('myCloudEventFunction', cloudEvent => {
  // Your code here
  // Access the CloudEvent data payload using cloudEvent.data
});

Agrega las siguientes dependencias en tu archivo package.json:

  {
    "dependencies": {
      "@google-cloud/functions-framework": "^3.0.0"
    }
  }

En Node.js, registras una función del controlador de CloudEvent con Functions Framework para Node.js. Tu función de controlador debe aceptar un objeto CloudEvent como argumento.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es myCloudEventFunction.

Python

import functions_framework

# Register a CloudEvent function with the Functions Framework
@functions_framework.cloud_event
def my_cloudevent_function(cloud_event):
  # Your code here
  # Access the CloudEvent data payload via cloud_event.data

En Python, registras una función del controlador de CloudEvent con Functions Framework para Python. Tu función de controlador debe aceptar un objeto CloudEvent como argumento.

El punto de entrada de la función es el nombre de la función del controlador registrada en Functions Framework. En este ejemplo, el punto de entrada es my_cloudevent_function.

Go

package mycloudeventfunction

import (
    "context"

    "github.com/GoogleCloudPlatform/functions-framework-go/functions"
    "github.com/cloudevents/sdk-go/v2/event"
)

func init() {
    // Register a CloudEvent function with the Functions Framework
    functions.CloudEvent("MyCloudEventFunction", myCloudEventFunction)
}

// Function myCloudEventFunction accepts and handles a CloudEvent object
func myCloudEventFunction(ctx context.Context, e event.Event) error {
    // Your code here
    // Access the CloudEvent data payload using e.Data() or e.DataAs(...)

    // Returning an error causes its message to be logged.
    // Example:
    err := myInternalFunction() // may return an error
    if err != nil {
        // Append error message to log
        return err
    }

    // Return nil if no error occurred
    return nil
}

En Go, registras una función del controlador de CloudEvent con Functions Framework para Go. Tu función de controlador debe aceptar un objeto event.Event de CloudEvents como argumento.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es MyCloudEventFunction.

Java

package mycloudeventfunction;

import com.google.cloud.functions.CloudEventsFunction;
import io.cloudevents.CloudEvent;

// Define a class that implements the CloudEventsFunction interface
public class MyCloudEventFunction implements CloudEventsFunction {
  // Implement the accept() method to handle CloudEvents
  @Override
  public void accept(CloudEvent event) {
    // Your code here
    // Access the CloudEvent data payload using event.getData()
    // To get the data payload as a JSON string, use:
    // new String(event.getData().toBytes())
  }
}

En Java, usas la API de Functions Framework para Java a fin de implementar una clase de controlador de CloudEvent con la interfaz CloudEventsFunction. El método accept() debe aceptar un objeto CloudEvent como argumento y realizar cualquier procesamiento en el evento.

El punto de entrada de la función es el nombre completamente calificado de la clase de controlador de CloudEvent, incluido el nombre del paquete. En este ejemplo, el punto de entrada es mycloudeventfunction.MyCloudEventFunction.

.NET

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using System.Threading;
using System.Threading.Tasks;

namespace MyProject
{
  // Define a class that implements the ICloudEventFunction<T> interface
  public class MyCloudEventFunction : ICloudEventFunction<CloudEventDataType>
  {
      // Implement the HandleAsync() method to handle CloudEvents
      public Task HandleAsync(CloudEvent cloudEvent, CloudEventDataType data, CancellationToken cancellationToken)
      {
          // Your code here
          // The data argument represents the CloudEvent data payload

          // Signal function completion
          return Task.CompletedTask;
      }
  }
}

En los entornos de ejecución de .NET, usas Functions Framework para .NET a fin de implementar una clase de controlador de CloudEvent con la interfaz de ICloudEventFunction<T>. El método HandleAsync() acepta un objeto CloudEvent y la carga útil de datos de CloudEvent asociada como argumentos.

El tipo de argumento de carga útil de datos de CloudEvent, que se muestra en el código de ejemplo como CloudEventDataType, debe corresponder al tipo de evento que maneja la función. La biblioteca .NET de Google CloudEvents proporciona tipos de datos para los distintos eventos compatibles con Google.

El punto de entrada de la función es el nombre completamente calificado de la clase de controlador de CloudEvent, incluido el espacio de nombres. En este ejemplo, el punto de entrada es MyProject.MyCloudEventFunction.

Ruby

require "functions_framework"

# Register a CloudEvent function with the Functions Framework
FunctionsFramework.cloud_event "my_cloudevent_function" do |cloud_event|
  # Your code here
  # Access the CloudEvent data payload via cloud_event.data
end

En Ruby, registra una función del controlador de CloudEvent con Functions Framework para Ruby. Tu función de controlador debe aceptar un objeto Event de CloudEvents como argumento.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es my_cloudevent_function.

PHP

<?php

use CloudEvents\V1\CloudEventInterface;
use Google\CloudFunctions\FunctionsFramework;

// Register a CloudEvent function with the Functions Framework
FunctionsFramework::cloudEvent('myCloudEventFunction', 'myCloudEventHandler');

// Define your CloudEvent handler
function myCloudEventHandler(CloudEventInterface $event): void
{
    // Your code here
    // Access the CloudEvent data payload using $event->getData()
}

En PHP, registra una función de controlador de CloudEvent con Functions Framework para PHP. La función del controlador debe aceptar un argumento que se ajuste a la interfaz CloudEventInterface.

El punto de entrada de la función es el nombre con el que se registra el controlador en Functions Framework. En este ejemplo, el punto de entrada es myCloudEventFunction.

Para las funciones basadas en eventos, los datos de eventos se pasan a tu función en el formato de CloudEvents, con una carga útil de datos de CloudEvent correspondiente al tipo de evento que activa la función. Consulta Activadores de funciones para obtener información sobre los activadores admitidos, los tipos de eventos y los formatos de datos de eventos asociados.

El repositorio de Eventos de Google contiene recursos para trabajar con CloudEvents emitidos por Google.

Finalización de la función

Cloud Run considera que la ejecución de la función controlada por eventos se completa cuando la función muestra un resultado. Si la función crea tareas en segundo plano (como subprocesos, futuros, objetos Promise de JavaScript, devoluciones de llamada o procesos del sistema), debes finalizar o resolver estas tareas antes de regresar de tu función. Es posible que no se completen las tareas que no se finalicen antes de que se muestre la función, lo que puede causar un comportamiento indefinido.

Reintentos automáticos

Las funciones controladas por eventos se pueden configurar para reintentar de forma automática las invocaciones con errores. Consulta Reintenta las funciones controladas por eventos para obtener más información.

¿Qué sigue?