Scrivere funzioni HTTP

Nelle funzioni Cloud Run, utilizzi le funzioni HTTP quando vuoi richiamare una funzione tramite una richiesta HTTP(S). Per consentire la semantica HTTP, le firme delle funzioni HTTP accettano argomenti specifici per HTTP.

Implementazione

L'esempio seguente mostra un file di origine della funzione HTTP di base per ogni runtime. Consulta la sezione Struttura della directory di origine per informazioni su dove trovare il codice sorgente.

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

In Node.js, registri una funzione di gestore HTTP con il Framework di funzioni per Node.js. La tua funzione di gestore HTTP deve essere un Funzione middleware Express che accetta la richiesta e response e invia un Risposta HTTP.

Le funzioni Cloud Run analizzano automaticamente il corpo della richiesta in base all'header Content-Type della richiesta utilizzando body-parser, in modo da poter accedere agli oggetti req.body e req.rawBody nel gestore HTTP.

Il punto di ingresso della funzione è il nome con cui il gestore è registrato nel Functions Framework. In questo esempio, il punto di ingresso è 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'

In Python, registri una funzione di gestore HTTP con il Framework di Functions per Python. La tua funzione di gestore HTTP deve accettare un Richiesta di flask oggetto come argomento e restituisce un valore che Flask può convertire in un oggetto di risposta HTTP.

Il punto di ingresso della funzione è il nome della funzione di gestore registrata nel Functions Framework. In questo esempio, il punto di ingresso è my_http_function.

Vai

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

In Go, registri una funzione di gestore HTTP con il Framework delle funzioni per Go nella funzione init(). La tua funzione di gestore HTTP deve utilizzare lo standard http.HandlerFunc a riga di comando per inviare una risposta HTTP.

Il punto di ingresso della funzione è il nome con cui il gestore è registrato nel Functions Framework. In questo esempio, il punto di ingresso è MyHTTPFunction.

La tua funzione di gestore HTTP deve implementare lo standard http.HandlerFunc a riga di comando. Accetta un'interfaccia http.ResponseWriter utilizzata dalla tua funzione per creare una risposta alla richiesta e un puntatore a uno struct http.Request contenente i dettagli del richiesta HTTP in entrata.

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

In Java, utilizzi API Java del framework Functions per implementare una classe di gestore HTTP HttpFunction a riga di comando. Il metodo service() deve inviare una risposta HTTP.

Il punto di ingresso della funzione è il nome completo della classe di gestore HTTP, incluso il nome del pacchetto. In questo esempio, il punto di ingresso è myhttpfunction.MyHttpFunction.

Il tuo metodo service riceve un HttpRequest che descrive la richiesta HTTP in entrata e HttpResponse che la funzione compila con un messaggio di risposta.

C#

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

Nei runtime .NET, utilizzi Framework di funzioni per .NET per implementare una classe di gestore HTTP IHttpFunction a riga di comando. Il metodo HandleAsync() accetta un oggetto ASP.NET HttpContext standard come argomento e deve inviare una risposta HTTP.

Il punto di ingresso della funzione è il nome completo della classe di gestore HTTP, incluso lo spazio dei nomi. In questo esempio, il punto di ingresso è 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

In Ruby, registri una funzione di gestore HTTP con il Functions Framework per Ruby. La funzione del gestore HTTP deve accettare un oggetto Rack request come argomento e restituire un valore che può essere utilizzato come risposta HTTP.

La punto di accesso alla funzione è il nome con cui il gestore viene registrato nel framework di Functions. In questo esempio, il punto di ingresso è 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';
}

In PHP, registri una funzione di gestore HTTP con il Framework di funzioni per PHP. La funzione del gestore HTTP deve accettare un argomento che implementa l'interfaccia PSR-7 ServerRequestInterface e deve restituire una risposta HTTP come stringa o come oggetto che implementa l'interfaccia PSR-7 ResponseInterface

La punto di accesso alla funzione è il nome con cui il gestore viene registrato nel framework di Functions. In questo esempio, il punto di ingresso è myHttpFunction.

Richieste e risposte HTTP

Le funzioni HTTP accettano i metodi di richiesta HTTP elencati nella pagina Trigger HTTP. Il gestore HTTP può esaminare il metodo di richiesta ed eseguire azioni diverse in base al metodo.

La funzione deve inviare una risposta HTTP. Se la funzione crea uno sfondo (come thread, future, oggetti Promise JavaScript, callback, o processi di sistema), devi terminare o risolvere in altro modo queste attività prima tramite l'invio di una risposta HTTP. Eventuali attività non terminate prima dell'invio della risposta HTTP potrebbero non essere completate e causare un comportamento non definito.

Per ulteriori informazioni, consulta Trigger HTTP informazioni sulle funzioni HTTP e sulle opzioni associate.

Gestione di CORS

La condivisione delle risorse tra origini (CORS) è un modo per consentire alle applicazioni in esecuzione in un dominio di accedere alle risorse di un altro dominio. Ad esempio, potresti dover consentire al tuo dominio di effettuare richieste Cloud Run Functions per accedere alla funzione.

Se CORS non è configurato correttamente, potrebbero essere visualizzati errori come i seguenti:

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.

Per consentire le richieste cross-origin alla tua funzione, imposta l'intestazione Access-Control-Allow-Origin in base alle esigenze nella risposta HTTP. Per le richieste cross-origin con preflight, devi rispondere alla richiesta OPTIONS di preflight con un codice di risposta 204 e intestazioni aggiuntive.

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)

Vai


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

C#

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

Limitazioni CORS

Per le richieste multiorigine con preflight, vengono inviate richieste OPTIONS preflight senza intestazione Authorization, quindi verranno rifiutate su tutte le richieste HTTP che richiedono l'autenticazione. Poiché le richieste di preflight non vanno a buon fine, anche le richieste principali non andranno a buon fine. Per aggirare questa limitazione, utilizza una delle seguenti opzioni: le seguenti opzioni:

Passaggi successivi