Menulis fungsi Cloud Run

Halaman ini menjelaskan cara menulis fungsi Cloud Run berbasis HTTP dan berbasis peristiwa dengan Functions Framework.

Ringkasan Functions Framework

Saat menulis kode sumber fungsi, Anda harus menggunakan Functions Framework, library open source untuk menulis fungsi Cloud Run. Dengan Functions Framework, Anda dapat menulis fungsi ringan yang berjalan di Cloud Run dan di lingkungan lain, termasuk mesin pengembangan lokal dan lingkungan berbasis Knative.

Dengan Functions Framework, Anda dapat:

  • Panggil fungsi Cloud Run sebagai respons terhadap permintaan.
  • Secara otomatis membatalkan marshal peristiwa yang sesuai dengan spesifikasi CloudEvents, yaitu spesifikasi standar industri untuk mendeskripsikan data peristiwa dengan cara yang umum.
  • Mulai server pengembangan lokal untuk pengujian.

Functions Framework menyediakan antarmuka untuk membangun layanan modular. Untuk menggunakan Functions Framework dalam kode sumber Anda, tentukan hal berikut:

Titik entri fungsi

Kode sumber Anda harus menentukan titik entri fungsi, yaitu kode yang berjalan saat Cloud Run memanggil fungsi Anda. Anda menentukan titik entri ini saat men-deploy fungsi.

Cara Anda menentukan titik entri bergantung pada runtime bahasa yang Anda gunakan. Beberapa bahasa menggunakan fungsi sebagai titik entri, sementara bahasa lain menggunakan class.

Jenis Tanda Tangan

Saat menulis kode sumber fungsi dengan Functions Framework, Anda harus menentukan salah satu dari dua jenis tanda tangan:

  • Fungsi HTTP: Mendaftarkan fungsi penanganan HTTP. Gunakan fungsi HTTP jika fungsi Anda memerlukan endpoint URL dan harus merespons permintaan HTTP, seperti untuk webhook.
  • Fungsi berbasis peristiwa, juga dikenal sebagai fungsi CloudEvents: Mendaftarkan fungsi pengendali CloudEvents. Gunakan fungsi berbasis peristiwa jika fungsi Anda dipicu secara langsung sebagai respons terhadap peristiwa dalam project Google Cloud Anda, seperti pesan tentang topik Pub/Sub atau perubahan dalam bucket Cloud Storage.

Struktur direktori sumber

Functions Framework didukung di sejumlah bahasa pemrograman. Runtime bahasa yang Anda pilih dan jenis fungsi yang ingin ditulis menentukan cara menyusun kode dan mengimplementasikan fungsi Anda.

Agar Cloud Run dapat menemukan definisi fungsi Anda, setiap runtime bahasa memiliki persyaratan untuk menyusun kode sumber.

Node.js

Struktur direktori dasar untuk fungsi Node.js adalah sebagai berikut:

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

Secara default, Cloud Run akan mencoba memuat kode sumber dari file bernama index.js di root direktori fungsi Anda. Untuk menentukan file sumber utama yang berbeda, gunakan kolom main di file package.json Anda.

File package.json Anda juga harus menyertakan Functions Framework for Node.js sebagai dependensi:

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

Kode dalam file utama harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta modul Node.js. File utama juga dapat menentukan beberapa titik entri fungsi yang dapat di-deploy secara terpisah.

Lihat ringkasan runtime Node.js dan Functions Framework for Node.js untuk mengetahui detail selengkapnya.

Python

Struktur direktori dasar untuk fungsi Python adalah sebagai berikut:

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

Cloud Run memuat kode sumber dari file bernama main.py di root direktori fungsi Anda. Anda harus memberi nama file utama Anda main.py.

File requirements.txt Anda harus menyertakan Framework Fungsi untuk Python sebagai dependensi:

functions-framework==3.*

Kode dalam file main.py harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta dependensi eksternal seperti biasa. File main.py juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat Ringkasan runtime Python dan Functions Framework untuk Python untuk mengetahui detail selengkapnya.

Go

Struktur direktori dasar untuk fungsi Go adalah sebagai berikut:

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

Fungsi Anda harus berada dalam paket Go di root project Anda. Paket dan file sumbernya dapat memiliki nama apa pun, kecuali fungsi Anda tidak boleh berada dalam package main. Jika memerlukan paket main, misalnya untuk pengujian lokal, Anda dapat membuatnya di subdirektori:

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

File go.mod Anda harus menyertakan Functions Framework for Go sebagai dependensi:

module example.com/my-module

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

Kode dalam paket root harus menentukan titik entri fungsi dan dapat mengimpor kode lain dari subpaket dan dependensi seperti biasa. Paket Anda juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat Ringkasan runtime Go dan Functions Framework untuk Go untuk mengetahui detail selengkapnya.

Java

Struktur direktori dasar untuk fungsi Java adalah sebagai berikut:

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

File sumber Java Anda harus berada di bawah direktori src/main/java/ dan dapat memiliki nama apa pun. Jika file sumber Anda mendeklarasikan suatu paket, tambahkan direktori tambahan pada src/main/java dengan nama paket tersebut:

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

Sebaiknya tempatkan pengujian terkait di bawah subdirektori src/test/java/.

File pom.xml Anda harus menyertakan Functions Framework for Java sebagai dependensi:

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

Kode dalam file sumber harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta dependensi eksternal seperti biasa. File sumber Anda juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat ringkasan runtime Java dan Functions Framework untuk Java untuk mengetahui detail selengkapnya.

.NET

Struktur direktori dasar untuk fungsi .NET adalah sebagai berikut:

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

Anda dapat menyusun project seperti yang Anda lakukan pada kode sumber .NET lainnya. File sumber Anda dapat memiliki nama apa pun.

File project Anda harus menyertakan Functions Framework untuk .NET sebagai dependensi:

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

Kode dalam file sumber harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta dependensi eksternal seperti biasa. File sumber Anda juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat ringkasan runtime.NET dan Functions Framework untuk .NET untuk mengetahui detail selengkapnya.

Ruby

Struktur direktori dasar untuk fungsi Ruby adalah sebagai berikut:

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

Cloud Run memuat kode sumber dari file bernama app.rb di root direktori fungsi Anda. File utama Anda harus diberi nama app.rb.

File Gemfile Anda harus menyertakan Functions Framework for Ruby sebagai dependensi:

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

Kode dalam file app.rb harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta dependensi eksternal seperti biasa. File app.rb juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat Ringkasan runtime Ruby dan Functions Framework untuk Ruby untuk mengetahui detail selengkapnya.

PHP

Struktur direktori dasar untuk fungsi PHP adalah sebagai berikut:

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

Cloud Run memuat kode sumber dari file bernama index.php di root direktori fungsi Anda. Anda harus memberi nama file utama Anda index.php.

File composer.json Anda harus menyertakan Framework Functions untuk Python sebagai dependensi:

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

Kode dalam file index.php harus menentukan titik entri fungsi dan dapat mengimpor kode lain serta dependensi eksternal seperti biasa. File index.php juga dapat menentukan beberapa titik masuk fungsi yang dapat di-deploy secara terpisah.

Lihat ringkasan runtime PHP dan Functions Framework untuk PHP untuk mengetahui detail selengkapnya.

Jika Anda mengelompokkan beberapa fungsi ke dalam satu project, ketahuilah bahwa setiap fungsi mungkin akan memiliki kumpulan dependensi yang sama. Namun, beberapa fungsi mungkin tidak memerlukan semua dependensi.

Jika memungkinkan, sebaiknya bagi codebase multifungsi yang berukuran besar dan masukkan setiap fungsi dalam direktori level teratasnya sendiri seperti yang ditunjukkan dalam contoh sebelumnya, dengan file konfigurasi sumber dan project-nya sendiri. Pendekatan ini meminimalkan jumlah dependensi yang diperlukan untuk fungsi tertentu, sehingga mengurangi jumlah memori yang dibutuhkan fungsi Anda.

Menulis fungsi HTTP

Tulis fungsi HTTP saat Anda ingin memanggil fungsi melalui permintaan HTTP(S). Untuk memungkinkan semantik HTTP, Anda menggunakan Framework Function dan menentukan tanda tangan Fungsi HTTP untuk menerima argumen khusus HTTP.

Contoh berikut menunjukkan file sumber fungsi HTTP dasar untuk setiap runtime. Untuk contoh kerja lengkap, lihat Men-deploy fungsi Cloud Run menggunakan Google Cloud CLI. Untuk mengetahui informasi selengkapnya tentang lokasi kode sumber, lihat Struktur direktori sumber.

Node.js

Modul ES

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

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

Tambahkan dependensi berikut, termasuk "type": "module" di file package.json Anda:

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

Modul 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');
  });

Tambahkan dependensi berikut di file package.json Anda:

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

Di Node.js, Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework untuk Node.js. Fungsi pengendali HTTP Anda harus berupa fungsi middleware Express yang menerima argumen permintaan dan respons serta mengirim respons HTTP.

Cloud Run secara otomatis mengurai isi permintaan untuk Anda berdasarkan header Content-Type permintaan menggunakan body-parser, sehingga Anda dapat mengakses req.body dan req.rawBody di pengendali HTTP Anda.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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'

Di Python, Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework untuk Python. Fungsi pengendali HTTP harus menerima objek permintaan Flask sebagai argumen dan menampilkan nilai yang dapat dikonversi Flask menjadi objek respons HTTP.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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")
}

Di Go, Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework untuk Go dalam fungsi init(). Fungsi pengendali HTTP Anda harus menggunakan antarmuka http.HandlerFunc standar untuk mengirim respons HTTP.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah MyHTTPFunction.

Fungsi pengendali HTTP Anda harus mengimplementasikan antarmuka http.HandlerFunc standar. Fungsi ini menerima antarmuka http.ResponseWriter yang digunakan fungsi Anda untuk membuat balasan terhadap permintaan, dan pointer ke struct http.Request yang berisi detail permintaan HTTP masuk.

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

Di Java, Anda menggunakan Functions Framework Java API untuk mengimplementasikan class pengendali HTTP dengan antarmuka HttpFunction. Metode service() harus mengirimkan respons HTTP.

Titik entri fungsi adalah nama yang sepenuhnya memenuhi syarat dari class pengendali HTTP, termasuk nama paket. Dalam contoh ini, titik masuknya adalah myhttpfunction.MyHttpFunction.

Metode service Anda menerima objek HttpRequest yang menjelaskan permintaan HTTP masuk, dan objek HttpResponse yang diisi fungsi Anda dengan pesan respons.

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

Pada runtime .NET, Anda menggunakan classFramework Functions untuk .NET untuk mengimplementasikan class pengendali HTTP dengan antarmuka IHttpFunction. Metode HandleAsync() menerima objek HttpContext ASP.NET standar sebagai argumen dan harus mengirim respons HTTP.

Titik entri fungsi adalah nama yang sepenuhnya memenuhi syarat dari class pengendali HTTP, termasuk namespace. Dalam contoh ini, titik masuknya adalah 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

Di Ruby, Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework untuk Ruby. Fungsi pengendali HTTP Anda harus menerima objek Permintaan Rack sebagai argumen dan menampilkan nilai yang dapat digunakan sebagai respons HTTP.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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';
}

Di PHP, Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework untuk PHP. Fungsi pengendali HTTP Anda harus menerima argumen yang menerapkan antarmuka ServerRequestInterface PSR-7, dan harus menampilkan respons HTTP sebagai string atau objek yang menerapkan antarmuka ResponseInterface PSR-7.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah myHttpFunction.

Permintaan dan respons HTTP

Saat Anda mendaftarkan fungsi pengendali HTTP dengan Functions Framework, pengendali HTTP Anda dapat memeriksa metode permintaan dan menjalankan berbagai tindakan berdasarkan metode tersebut.

Saat Anda mengonfigurasi penyedia peristiwa untuk mengirim permintaan HTTP ke fungsi Cloud Run, fungsi Anda akan mengirim respons HTTP. Jika fungsi membuat tugas latar belakang (seperti pada thread, future, objek Promise JavaScript, callback, atau proses sistem), Anda harus menghentikan atau menyelesaikan tugas ini sebelum mengirimkan respons HTTP. Setiap tugas yang tidak dihentikan sebelum respons HTTP dikirim mungkin tidak akan diselesaikan, dan dapat menyebabkan perilaku yang tidak ditentukan.

Menangani CORS

Cross-Origin Resource Sharing (CORS) adalah cara untuk memungkinkan aplikasi yang berjalan di satu domain mengakses resource dari domain lain. Misalnya, Anda mungkin perlu mengizinkan domain Anda membuat permintaan ke domain fungsi Cloud Run untuk mengakses fungsi Anda.

Untuk mengizinkan permintaan lintas asal ke fungsi Anda, tetapkan header Access-Control-Allow-Origin yang sesuai pada respons HTTP Anda. Untuk permintaan lintas asal yang telah diproses sebelumnya, Anda harus merespons permintaan OPTIONS preflight dengan kode respons 204 dan header tambahan.

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

Jika CORS tidak disiapkan dengan benar, Anda mungkin melihat error seperti berikut:

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.

Batasan CORS

Untuk permintaan lintas asal yang di-preflight, permintaan OPTIONS preflight dikirim tanpa header Otorisasi, sehingga akan ditolak pada semua fungsi HTTP yang memerlukan autentikasi. Karena permintaan preflight gagal, permintaan utama juga akan gagal. Untuk mengatasi keterbatasan ini, gunakan salah satu opsi berikut:

Menulis fungsi berbasis peristiwa

Tulis fungsi berbasis peristiwa jika Anda ingin fungsi dipicu secara langsung sebagai respons terhadap peristiwa dalam project Google Cloud Anda, seperti pesan pada topik Pub/Sub atau perubahan dalam bucket Cloud Storage.

Fungsi berbasis peristiwa didasarkan pada CloudEvents, yaitu spesifikasi standar industri untuk mendeskripsikan data peristiwa dengan cara yang umum. Anda dapat mempelajari spesifikasi CloudEvents lebih lanjut di repositori GitHub CloudEvents. Project CloudEvents juga menyediakan sekumpulan CloudEvents SDK untuk membantu menangani objek CloudEvents dalam kode Anda.

Contoh berikut menunjukkan file sumber fungsi yang didorong peristiwa untuk setiap runtime. Lihat Struktur direktori sumber untuk mengetahui informasi tentang lokasi kode sumber.

Node.js

Modul ES

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

Tambahkan dependensi berikut, termasuk "type": "module" di file package.json Anda:

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

Modul 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
});

Tambahkan dependensi berikut di file package.json Anda:

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

Di Node.js, Anda mendaftarkan fungsi pengendali CloudEvent dengan Functions Framework untuk Node.js. Fungsi pengendali Anda harus menerima objek CloudEvent sebagai argumen.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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

Dalam Python, Anda mendaftarkan fungsi pengendali CloudEvent dengan Functions Framework untuk Python. Fungsi pengendali Anda harus menerima objek CloudEvent sebagai argumen.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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
}

Di Go, Anda mendaftarkan fungsi pengendali CloudEvent dengan Functions Framework untuk Go. Fungsi pengendali Anda harus menerima CloudEvent event.Event sebagai argumen.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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())
  }
}

Di Java, Anda menggunakan Functions Framework Java API untuk mengimplementasikan class pengendali CloudEvent dengan antarmuka CloudEventsFunction. Metode accept() harus menerima objek CloudEvent sebagai argumen dan melakukan pemrosesan apa pun pada peristiwa.

Titik entri fungsi adalah nama yang sepenuhnya memenuhi syarat untuk class pengendali CloudEvent, termasuk nama paket. Dalam contoh ini, titik masuknya adalah 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;
      }
  }
}

Pada runtime .NET, Anda menggunakan classFramework Functions untuk .NET untuk menerapkan class pengendali CloudEvent dengan antarmuka ICloudEventFunction<T>. Metode HandleAsync() menerima objek CloudEvent dan payload data CloudEvent terkait sebagai argumen.

Jenis argumen payload data CloudEvent, yang ditunjukkan dalam kode contoh sebagai CloudEventDataType, harus sesuai dengan jenis peristiwa yang ditangani fungsi. Library .NET Google CloudEvents menyediakan jenis data untuk berbagai peristiwa yang didukung oleh Google.

Titik entri fungsi adalah nama yang sepenuhnya memenuhi syarat untuk class pengendali CloudEvent, termasuk namespace. Dalam contoh ini, titik masuknya adalah 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

Dalam Ruby, Anda mendaftarkan fungsi pengendali CloudEvent dengan Functions Framework untuk Ruby. Fungsi pengendali Anda harus menerima objek Event CloudEvent sebagai argumen.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah 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()
}

Di PHP, Anda mendaftarkan fungsi pengendali CloudEvent dengan Functions Framework untuk PHP. Fungsi pengendali Anda harus menerima argumen yang sesuai dengan antarmuka CloudEventInterface.

Titik entri fungsi adalah nama yang digunakan pengendali untuk mendaftar pada Functions Framework. Dalam contoh ini, titik masuknya adalah myCloudEventFunction.

Untuk fungsi berbasis peristiwa, data peristiwa diteruskan ke fungsi Anda dalam format CloudEvents, dengan payload data CloudEvent yang sesuai dengan jenis peristiwa yang memicu fungsi Anda. Lihat Pemicu fungsi untuk mengetahui informasi tentang pemicu yang didukung, jenis peristiwa, dan format data peristiwa terkait.

Repositori Google Events berisi resource untuk bekerja dengan CloudEvents yang dikeluarkan oleh Google.

Penghentian fungsi

Cloud Run menganggap eksekusi fungsi berbasis peristiwa selesai saat fungsi tersebut dikembalikan. Jika fungsi membuat tugas latar belakang (seperti dengan thread, future, objek Promise JavaScript, callback, atau proses sistem), Anda harus menghentikan atau menyelesaikan tugas ini sebelum kembali dari fungsi. Setiap tugas yang tidak dihentikan sebelum fungsi ditampilkan mungkin belum diselesaikan, dan dapat menyebabkan perilaku yang tidak ditentukan.

Percobaan ulang otomatis

Fungsi berbasis peristiwa dapat dikonfigurasi untuk mencoba kembali pemanggilan yang gagal secara otomatis. Lihat Mencoba kembali fungsi berbasis peristiwa untuk mengetahui informasi selengkapnya.

Langkah berikutnya