Menulis fungsi HTTP

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

Mengimplementasikan fungsi pengendali HTTP

Contoh berikut menunjukkan file sumber fungsi HTTP dasar untuk setiap runtime. Lihat Struktur direktori sumber untuk mengetahui informasi tentang lokasi kode sumber.

Node.js

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

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 objek 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 atas 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 mengimplementasikan 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 Framework Fungsi, pengendali HTTP Anda dapat memeriksa metode permintaan dan melakukan berbagai tindakan berdasarkan metode tersebut.

Saat Anda mengonfigurasi penyedia peristiwa untuk mengirim permintaan HTTP ke fungsi Cloud Run, fungsi Anda akan mengirimkan 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 dukungan CORs / 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 Authorization, 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:

Langkah selanjutnya