Escribir funciones de Cloud Run

En esta página se describe cómo escribir funciones de Cloud Run basadas en eventos y HTTP con el framework de Functions.

Información general sobre Functions Framework

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

Functions Framework te permite hacer lo siguiente:

  • Invocar una función de Cloud Run en respuesta a una solicitud.
  • Deserializa automáticamente los eventos que cumplen la especificación CloudEvents, una especificación estándar del sector para describir los datos de eventos de forma común.
  • Inicia un servidor de desarrollo local para hacer pruebas.

Functions Framework proporciona una interfaz para crear servicios modulares. Para usar Functions Framework en el código fuente, especifique 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. Este punto de entrada se especifica al desplegar la función.

La forma de definir el punto de entrada depende del tiempo de ejecución del lenguaje que utilices. 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 endpoint de URL y deba responder a solicitudes HTTP, como en el caso de los webhooks.
  • Funciones basadas en eventos, también conocidas como funciones de CloudEvents: registra una función de controlador de CloudEvents. Usa una función basada en eventos cuando se active directamente en respuesta a eventos de tu Google Cloud proyecto, como mensajes de un tema de Pub/Sub o cambios en un segmento de Cloud Storage.

Estructura del directorio de origen

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

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

Node.js

La estructura de directorios básica de las funciones de Node.js es la siguiente:

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

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

Tu archivo package.json también debe incluir Functions Framework para Node.js como 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 otro código 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 información general sobre el tiempo de ejecución de Node.js y el Functions Framework para Node.js para obtener más información.

Python

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

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

Cloud Run carga el código fuente de un archivo llamado main.py en la raíz del directorio de la función. El archivo principal debe llamarse main.py.

Tu archivo requirements.txt debe incluir Functions Framework para Python como 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 como de costumbre. El archivo main.py también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Consulta la información general sobre el entorno de ejecución de Python y el Functions Framework para Python para obtener más información.

Go

La estructura básica de los directorios de 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 package main. Si necesitas un paquete main, por ejemplo, para hacer pruebas locales, puedes crear uno en un subdirectorio:

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

Tu archivo go.mod debe incluir Functions Framework para Go como 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 la función y puede importar otro código de subpaquetes y dependencias de forma normal. Tu paquete también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Consulta más información en la descripción general del tiempo de ejecución de Go y en el Functions Framework para Go.

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 los archivos de origen declaran un paquete, añade un directorio adicional en src/main/java con el nombre del paquete:

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

Te recomendamos que pongas las pruebas asociadas en un subdirectorio src/test/java/.

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

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

El código de los 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 se pueden implementar por separado.

Consulta más información en la descripción general del tiempo de ejecución de Java y en Functions Framework para Java.

.NET

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

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

Puede estructurar sus proyectos como cualquier otro código fuente de .NET. Los archivos de origen pueden tener cualquier nombre.

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

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

El código de los 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 se pueden implementar por separado.

Consulta la información general sobre el entorno de ejecución de.NET y el Functions Framework para .NET para obtener más información.

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 la función. El archivo principal debe llamarse app.rb.

Tu archivo Gemfile debe incluir Functions Framework para Ruby como 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 como de costumbre. El archivo app.rb también puede definir varios puntos de entrada de funciones que se pueden implementar por separado.

Para obtener más información, consulta la información general sobre el entorno de ejecución de Ruby y Functions Framework para Ruby.

PHP

La estructura básica de los directorios de 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 la función. El archivo principal debe llamarse index.php.

Tu archivo composer.json debe incluir Functions Framework para PHP como 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 información general sobre el entorno de ejecución de PHP y el Functions Framework para PHP para obtener más información.

Si agrupas varias funciones en un mismo proyecto, ten en cuenta que es posible que todas las funciones compartan el mismo conjunto de dependencias. Sin embargo, es posible que algunas funciones no necesiten todas las dependencias.

Cuando sea posible, te recomendamos que dividas las bases de código multifunción grandes y que pongas 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. De esta forma, se minimiza el número de dependencias necesarias para una función concreta, lo que a su vez reduce la cantidad de memoria que necesita la función.

Escribir funciones HTTP

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

En el siguiente ejemplo se muestra un archivo de origen de función HTTP básico para cada tiempo de ejecución. Para ver un ejemplo práctico completo, consulta Desplegar una función de Cloud Run con Google Cloud CLI. Para obtener más información sobre dónde encontrar el código fuente, consulta Estructura del directorio de origen.

Node.js

Módulo ES

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

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

Añade las siguientes dependencias, incluida "type": "module", a 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');
  });

Añade las siguientes dependencias en tu archivo package.json:

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

En Node.js, se registra una función de controlador HTTP con el Functions Framework para Node.js. La función de controlador HTTP debe ser una función de middleware de Express que acepte los argumentos request y response y envíe una respuesta HTTP.

Cloud Run analiza automáticamente el cuerpo de la solicitud en función del encabezado Content-Type de la solicitud mediante body-parser, por lo que puedes 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 el controlador se registra 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, se registra una función de controlador HTTP con el Functions Framework para Python. Tu función de controlador HTTP debe aceptar un objeto solicitud de Flask como argumento y devolver un valor que Flask pueda convertir en un objeto de respuesta HTTP.

El punto de entrada de la función es el nombre con el que el controlador se registra 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, se registra una función de controlador HTTP con el Functions Framework para Go en la función init(). Tu función de controlador HTTP debe usar la interfaz estándar http.HandlerFunc para enviar una respuesta HTTP.

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

Tu función de controlador HTTP debe implementar la interfaz estándar http.HandlerFunc. Acepta una interfaz http.ResponseWriter que tu función usa para crear una respuesta a la solicitud y 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, se usa la API Java de Functions Framework para 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 completo 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 y un objeto HttpResponse que tu función rellena 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 tiempos de ejecución de .NET, se usa el Functions Framework para .NET para implementar una clase de controlador HTTP con la interfaz 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 completo 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, se registra una función de controlador HTTP con el Functions Framework para Ruby. Tu función de controlador HTTP debe aceptar un objeto solicitud de Rack como argumento y devolver un valor que se pueda usar como respuesta HTTP.

El punto de entrada de la función es el nombre con el que el controlador se registra 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, se registra una función de controlador HTTP con el Functions Framework para PHP. Tu función de controlador HTTP debe aceptar un argumento que implemente la interfaz PSR-7 ServerRequestInterface y debe devolver una respuesta HTTP como una cadena o un objeto que implemente la interfaz PSR-7 ResponseInterface.

El punto de entrada de la función es el nombre con el que el controlador se registra 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 la 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 (por ejemplo, con hilos, futuros, objetos Promise de JavaScript, retrollamadas o procesos del sistema), debes finalizar o resolver estas tareas antes de enviar una respuesta HTTP. Es posible que las tareas que no se hayan finalizado antes de que se envíe la respuesta HTTP no se completen y que provoquen un comportamiento indefinido.

Gestionar 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 recursos de otro dominio. Por ejemplo, puede que tengas que permitir que tu dominio haga solicitudes al dominio de las funciones de Cloud Run para acceder a tu función.

Para permitir las solicitudes de origen cruzado a tu función, define el encabezado Access-Control-Allow-Origin en la respuesta HTTP según corresponda. En el caso de las solicitudes de origen cruzado con comprobación previa, debes responder a la solicitud preparatoria OPTIONS 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 los siguientes:

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

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

Escribir funciones basadas en eventos

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

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

En el siguiente ejemplo se muestra un archivo de origen de función basada en eventos para cada tiempo de ejecución. Consulta la estructura del directorio de origen para saber dónde encontrar el código fuente.

Node.js

Módulo ES

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

Añade las siguientes dependencias, incluida "type": "module", a 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
});

Añade las siguientes dependencias en tu archivo package.json:

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

En Node.js, se registra una función de controlador de CloudEvents con el 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 el controlador se registra 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, se registra una función de controlador de CloudEvents con el 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 de 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, se registra una función de controlador de CloudEvents con el Functions Framework para Go. La 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 el controlador se registra 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, se usa la API de Java de Functions Framework para implementar una clase de controlador de CloudEvents 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 completo de la clase de controlador de CloudEvents, 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 tiempos de ejecución de .NET, se usa el Functions Framework para .NET para implementar una clase de controlador de CloudEvents con la interfaz ICloudEventFunction<T>. El método HandleAsync() acepta un objeto CloudEvent y la carga útil de datos de CloudEvent asociada como argumentos.

El tipo del 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 gestiona la función. La biblioteca .NET de Google CloudEvents proporciona tipos de datos para los distintos eventos admitidos por Google.

El punto de entrada de la función es el nombre completo 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, se registra una función de controlador de CloudEvent con el Functions Framework para Ruby. Tu función de controlador debe aceptar un objeto CloudEvents Event como argumento.

El punto de entrada de la función es el nombre con el que el controlador se registra 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, se registra una función de controlador de CloudEvents con el framework de funciones de PHP. Tu función de controlador debe aceptar un argumento que cumpla la interfaz CloudEventInterface.

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

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

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

Finalización de la función

Cloud Run considera que la ejecución de una función basada en eventos se ha completado cuando la función devuelve un valor. Si la función crea tareas en segundo plano (por ejemplo, con hilos, futuros, objetos Promise de JavaScript, retrollamadas o procesos del sistema), debes finalizar o resolver estas tareas antes de volver de la función. Es posible que las tareas que no se hayan finalizado antes de que la función devuelva un valor no se completen y provoquen un comportamiento indefinido.

Reintentos automáticos

Las funciones basadas en eventos se pueden configurar para que vuelvan a intentar automáticamente las invocaciones fallidas. Consulta más información en Volver a intentar funciones basadas en eventos.

Siguientes pasos