HTTP-Funktionen schreiben

In Cloud Run Functions verwenden Sie HTTP-Funktionen, wenn Sie eine Funktion über eine HTTP(S)-Anfrage aufrufen möchten. Die HTTP-Funktionssignaturen akzeptieren HTTP-spezifische Argumente, und ermöglichen so HTTP-Semantik.

Implementierung

Das folgende Beispiel zeigt eine einfache Quelldatei der HTTP-Funktion für jede Laufzeit. Informationen zur Position Ihres Quellcodes finden Sie unter Quellverzeichnisstruktur.

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 registrieren Sie eine HTTP-Handler-Funktion mit dem Functions Framework für Node.js. Ihre HTTP-Handler-Funktion muss eine Express-Middleware-Funktion sein, die die Anfrage- und Antwortargumente akzeptiert und eine HTTP-Antwort sendet.

Cloud Run Functions parst den Anfragetext automatisch anhand des Content-Type-Headers der Anfrage mithilfe von body-parser, sodass Sie auf req.body und req.rawBody-Objekte im HTTP-Handler zugreifen können.

Der Funktionseinstiegspunkt ist der Name, mit dem der Handler beim Functions Framework registriert ist. In diesem Beispiel ist der Einstiegspunkt 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 registrieren Sie eine HTTP-Handler-Funktion mit dem Functions Framework für Python. Ihre HTTP-Handler-Funktion muss ein Flask-Anfrageobjekt als Argument akzeptieren und einen Wert zurückgeben, den Flask in ein HTTP-Antwortobjekt konvertieren kann.

Der Funktionseinstiegspunkt ist der Name der Handler-Funktion, die bei Functions Framework registriert ist. In diesem Beispiel ist der Einstiegspunkt 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")
}

In Go registrieren Sie eine HTTP-Handler-Funktion mit dem Functions Framework für Go in Ihrer init()-Funktion. Ihre HTTP-Handler-Funktion muss die Standardschnittstelle http.HandlerFunc verwenden, um eine HTTP-Antwort zu senden.

Der Funktionseinstiegspunkt ist der Name, mit dem der Handler beim Functions Framework registriert ist. In diesem Beispiel ist der Einstiegspunkt MyHTTPFunction.

Ihre HTTP-Handler-Funktion muss die Standardschnittstelle http.HandlerFunc implementieren. Sie akzeptiert eine http.ResponseWriter-Schnittstelle, mit der Ihre Funktion eine Antwort auf die Anfrage erstellt und einen Verweis auf eine http.Request-Struktur, die die Details der eingehenden HTTP-Anfrage enthält.

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 verwenden Sie die Functions Framework Java API, um eine HTTP-Handler-Klasse mit der Schnittstelle HttpFunction zu implementieren. Die Methode service() muss eine HTTP-Antwort senden.

Der Funktionseinstiegspunkt ist der voll qualifizierte Name der HTTP-Handler-Klasse, einschließlich des Paketnamens. In diesem Beispiel ist der Einstiegspunkt myhttpfunction.MyHttpFunction.

Die Methode service empfängt ein HttpRequest-Objekt, das die eingehende HTTP-Anfrage beschreibt, und ein HttpResponse-Objekt, das von der Funktion mit einer Antwortnachricht ausgefüllt wird.

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

In .NET-Laufzeiten verwenden Sie das Functions Framework für .NET, um eine HTTP-Handler-Klasse mit der Benutzeroberfläche IHttpFunction. Die Methode HandleAsync() akzeptiert ein Standard-ASP.NET-Objekt HttpContext als Argument und muss eine HTTP-Antwort senden.

Der Funktionseinstiegspunkt ist der vollständig qualifizierte Name der HTTP-Handler-Klasse, einschließlich des Namespace. In diesem Beispiel ist der Einstiegspunkt 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 registrieren Sie eine HTTP-Handler-Funktion mit dem Functions Framework für Ruby. Die HTTP-Handler-Funktion muss ein Rack-Anfrageobjekt als Argument akzeptieren und einen Wert zurückgeben, der als HTTP-Antwort verwendet werden kann.

Der Funktionseinstiegspunkt ist der Name, mit dem der Handler beim Functions Framework registriert ist. In diesem Beispiel ist der Einstiegspunkt 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 registrieren Sie eine HTTP-Handler-Funktion mit dem Functions Framework für PHP. Ihre HTTP-Handler-Funktion muss ein Argument akzeptieren, das die PSR-7-Schnittstelle ServerRequestInterface implementiert, und muss eine HTTP-Antwort als String oder Objekt zurückgeben, das implementiert die PSR-7 Schnittstelle ResponseInterface.

Der Funktionseinstiegspunkt ist der Name, mit dem der Handler beim Functions Framework registriert ist. In diesem Beispiel ist der Einstiegspunkt myHttpFunction.

HTTP-Anfragen und -Antworten

HTTP-Funktionen akzeptieren die auf der Seite HTTP-Trigger aufgeführten HTTP-Anfragemethoden. Ihr HTTP-Handler kann die Anfragemethode prüfen und je nach Methode verschiedene Aktionen ausführen.

Ihre Funktion muss eine HTTP-Antwort senden. Wenn die Funktion Hintergrundaufgaben erstellt (z. B. mit Threads, Futures, JavaScript-Promise-Objekten, -Callbacks oder Systemprozessen), müssen Sie diese Aufgaben vor dem Senden einer HTTP-Antwort beenden oder anderweitig auflösen. Alle Aufgaben, die vor dem Senden der HTTP-Antwort nicht beendet wurden, sind möglicherweise nicht abgeschlossen und können ein nicht definiertes Verhalten verursachen.

Weitere Informationen zu HTTP-Funktionen und zugehörigen Optionen finden Sie unter HTTP-Trigger.

CORS verarbeiten

Mit Cross-Origin Resource Sharing (CORS) können Anwendungen, die auf einer Domain ausgeführt werden, auf Ressourcen einer anderen Domain zugreifen. Sie müssen beispielsweise zulassen können, dass Ihre Domain Anfragen an die Cloud Run Functions-Domain sendet, um auf Ihre Funktion zuzugreifen.

Wenn CORS nicht richtig eingerichtet ist, werden möglicherweise folgende Fehler angezeigt:

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.

Setzen Sie den Header Access-Control-Allow-Origin entsprechend in Ihrer HTTP-Antwort, damit Cross-Origin-Anfragen an Ihre Funktion zugelassen werden. Bei Cross-Origin-Anfragen für Preflight-Anfragen müssen Sie auf die Preflight-Anfrage OPTIONS mit einem 204-Antwortcode und zusätzlichen Headern antworten.

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

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

CORS-Einschränkungen

Bei Preflight-Origin-Anfragen werden Preflight-OPTIONS-Anfragen ohne Authorization-Header gesendet. Daher werden sie bei allen HTTP-Funktionen abgelehnt, die eine Authentifizierung erfordern. Da die Preflight-Anfragen fehlschlagen, schlägt auch die Hauptanfrage fehl. Verwenden Sie eine der folgenden Optionen, um diese Einschränkung zu umgehen:

Weitere Informationen