Escrever funções HTTP

No Cloud Run functions, você usa funções HTTP quando quiser invocar uma função por meio de uma solicitação HTTP(S). Para permitir a semântica, as assinaturas da função HTTP aceitam argumentos específicos de HTTP.

Implementação

O exemplo a seguir mostra um arquivo de origem da função HTTP básico para cada ambiente de execução. Consulte Estrutura do diretório de origem para ver informações sobre onde localizar o código-fonte.

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

No Node.js, você registra uma função de gerenciador HTTP com o Framework do Functions para Node.js. A função de gerenciador HTTP precisa ser uma função de middleware Express que aceita os argumentos de solicitação e resposta e envia uma resposta HTTP.

O Cloud Run functions analisa automaticamente o corpo da solicitação com base no cabeçalho Content-Type da solicitação usando body-parser. Assim, você pode acessar req.body e Objetos req.rawBody no seu gerenciador HTTP.

O ponto de entrada de função é o nome com que o gerenciador está registrado no Functions Framework. Neste exemplo, o ponto de entrada é 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'

Em Python, você registra uma função de gerenciador HTTP com o Framework de funções para Python. A função de gerenciador HTTP precisa aceitar um objeto de solicitação do Flask como argumento e retornar um valor que o Flask pode converter em um objeto de resposta HTTP.

O ponto de entrada da função é o nome da função do gerenciador registrada no Functions Framework. Neste exemplo, o ponto de entrada é 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")
}

Em Go, registre uma função de gerenciador HTTP com o Framework de funções para Go na sua função init(). A função de gerenciador HTTP precisa usar a interface http.HandlerFunc padrão para enviar uma resposta HTTP.

O ponto de entrada de função é o nome com que o gerenciador está registrado no Functions Framework. Neste exemplo, o ponto de entrada é MyHTTPFunction.

Sua função de gerenciador HTTP precisa implementar a interface http.HandlerFunc padrão. Ele aceita uma interface http.ResponseWriter que sua função usa para criar uma resposta à solicitação e um ponteiro para um struct http.Request contendo os detalhes do solicitação HTTP recebida.

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

Em Java, use a API Functions Framework para Java para implementar uma classe de gerenciador HTTP com a interface HttpFunction. O método service() precisa enviar uma resposta HTTP.

O ponto de entrada de função é o nome totalmente qualificado da classe de gerenciador HTTP, incluindo o nome do pacote. Neste exemplo, o ponto de entrada é myhttpfunction.MyHttpFunction.

O método service recebe um objeto HttpRequest que descreve a solicitação HTTP de entrada e um objeto HttpResponse que sua função preenche com uma mensagem de resposta.

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

Nos ambientes de execução do .NET, use o Functions Framework para .NET para implementar uma classe de gerenciador HTTP com a interface IHttpFunction. O método HandleAsync() aceita um objeto HttpContext padrão do ASP.NET como argumento e precisa enviar uma resposta HTTP.

O ponto de entrada de função é o nome totalmente qualificado da classe de gerenciador HTTP, incluindo o namespace. Neste exemplo, o ponto de entrada é 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

No Ruby, você registra uma função de gerenciador HTTP com o frameworks Functions para Ruby. A função de gerenciador HTTP precisa aceitar um objeto Solicitação de rack como um argumento e retornar um valor que pode ser usado como uma resposta HTTP.

O ponto de entrada de função é o nome com que o gerenciador está registrado no Functions Framework. Neste exemplo, o ponto de entrada é 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';
}

Em PHP, você registra uma função de gerenciador HTTP com o Framework de funções para PHP. A função de gerenciador HTTP precisa aceitar um argumento que implemente a interface ServerRequestInterface do PSR-7 e retornar uma resposta HTTP como uma string ou um objeto que implemente a interface ResponseInterface do PSR-7.

O ponto de entrada de função é o nome com que o gerenciador está registrado no Functions Framework. Neste exemplo, o ponto de entrada é myHttpFunction.

Solicitações e respostas HTTP

As funções HTTP aceitam os métodos de solicitação HTTP listados na página Acionadores HTTP. Seu gerenciador HTTP pode inspecionar o método da solicitação e executar diferentes ações com base no método.

Sua função precisa enviar uma resposta HTTP. Se a função criar tarefas em segundo plano, como com linhas de execução, contratos futuros, objetos JavaScript Promise, callbacks ou processos do sistema), é necessário encerrar ou resolver essas tarefas antes de enviar uma resposta HTTP. Qualquer tarefa não encerrada antes do envio da resposta HTTP pode não ser concluída e pode causar um comportamento indefinido.

Consulte Acionadores HTTP para mais informações sobre funções HTTP e opções associadas.

Como gerenciar CORS

O Compartilhamento de recursos entre origens (CORS) é uma forma de permitir que aplicativos executados em um domínio acessem recursos de outro domínio. Por exemplo, talvez seja necessário permitir que o domínio faça solicitações ao domínio do Cloud Run functions para acessar a função.

Se o CORS não estiver configurado corretamente, poderão aparecer erros como os seguintes:

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.

Para permitir solicitação entre origens para sua função, defina o cabeçalho Access-Control-Allow-Origin conforme apropriado na sua resposta HTTP. Para solicitações de origem cruzada simuladas, é necessário responder à solicitação OPTIONS de simulação com um código de resposta 204 e cabeçalhos adicionais.

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

Limitações do CORS

Para solicitações de origem cruzada de simulação, as solicitações de simulação de OPTIONS são enviadas sem um cabeçalho Authorization. Portanto, elas serão rejeitadas em todas as funções HTTP que exigem autenticação. Como há falha nas solicitações simuladas, a solicitação principal também falhará. Para contornar essa limitação, use uma das seguintes opções:

Próximas etapas