HTTP 함수 작성

Cloud Run Functions에서는 HTTP(S) 요청을 통해 함수를 호출하려고 할 때 HTTP 함수를 사용합니다. HTTP 시맨틱스를 허용하기 위해 HTTP 함수 서명은 HTTP 관련 인수를 허용합니다.

구현

다음 예시에서는 각 런타임의 기본 HTTP 함수 소스 파일을 보여줍니다. 소스 코드를 찾을 위치에 대한 자세한 내용은 소스 디렉터리 구조를 참조하세요.

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

Node.js에서 Node.js용 함수 프레임워크에 HTTP 핸들러 함수를 등록합니다. HTTP 핸들러 함수는 요청응답 인수를 수락하고 HTTP 응답을 전송하는 Express 미들웨어 함수여야 합니다.

Cloud Run Functions는 HTTP 핸들러에서 req.bodyreq.rawBody 객체에 액세스할 수 있도록 body-parser를 사용하여 요청의 Content-Type 헤더에 따라 요청 본문을 자동으로 파싱합니다.

함수 진입점은 함수 프레임워크에 핸들러가 등록된 이름입니다. 이 예시에서 진입점은 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'

Python에서는 HTTP 핸들러 함수를 Python용 함수 프레임워크에 등록합니다. HTTP 핸들러 함수는 Flask 요청 객체를 인수로 수락하고 Flask가 HTTP 응답 객체로 변환할 수 있는 값을 반환해야 합니다.

함수 진입점은 함수 프레임워크에 등록된 핸들러 함수 이름입니다. 이 예시에서 진입점은 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")
}

Go에서는 init() 함수에서 Go용 함수 프레임워크에 HTTP 핸들러 함수를 등록합니다. HTTP 핸들러 함수는 표준 http.HandlerFunc 인터페이스를 사용하여 HTTP 응답을 전송해야 합니다.

함수 진입점은 함수 프레임워크에 핸들러가 등록된 이름입니다. 이 예시에서 진입점은 MyHTTPFunction입니다.

HTTP 핸들러 함수는 표준 http.HandlerFunc 인터페이스를 구현해야 합니다. 함수가 요청에 대한 응답을 만드는 데 사용하는 http.ResponseWriter 인터페이스와 인바운드 HTTP 요청의 세부정보가 포함된 http.Request 구조체에 대한 포인터를 받습니다.

자바

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

Java에서는 Functions Framework Java API를 사용하여 HttpFunction 인터페이스로 HTTP 핸들러 클래스를 구현합니다. service() 메서드는 HTTP 응답을 전송해야 합니다.

함수 진입점은 패키지 이름을 포함하여 HTTP 핸들러 클래스의 정규화된 이름입니다. 이 예시에서 진입점은 myhttpfunction.MyHttpFunction입니다.

service 메서드는 인바운드 HTTP 요청을 설명하는 HttpRequest 객체와 함수가 응답 메시지로 채우는 HttpResponse 객체를 수신합니다.

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

.NET 런타임에서는 .NET용 함수 프레임워크를 사용하여 IHttpFunction 인터페이스로 HTTP 핸들러 클래스를 구현합니다. HandleAsync() 메서드는 표준 ASP.NET HttpContext 객체를 인수로 수락하고 HTTP 응답을 전송해야 합니다.

함수 진입점은 네임스페이스를 포함하여 HTTP 핸들러 클래스의 정규화된 이름입니다. 이 예시에서 진입점은 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

Ruby에서는 Ruby용 함수 프레임워크로 HTTP 핸들러 함수를 등록합니다. HTTP 핸들러 함수는 Rack 요청 객체를 인수로 수락하고 HTTP 응답으로 사용될 수 있는 값을 반환해야 합니다.

함수 진입점은 함수 프레임워크에 핸들러가 등록된 이름입니다. 이 예시에서 진입점은 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';
}

PHP에서는 PHP용 함수 프레임워크로 HTTP 핸들러 함수를 등록합니다. HTTP 핸들러 함수는 PSR-7 ServerRequestInterface 인터페이스를 구현하는 인수를 수락하고 HTTP 응답을 PSR-7 ResponseInterface 인터페이스를 구현하는 문자열 또는 객체로 반환해야 합니다.

함수 진입점은 함수 프레임워크에 핸들러가 등록된 이름입니다. 이 예시에서 진입점은 myHttpFunction입니다.

HTTP 요청 및 응답

HTTP 함수는 HTTP 트리거 페이지에 나열된 HTTP 요청 메서드를 수락합니다. HTTP 핸들러는 요청 메서드를 조사하고 메서드에 따라 여러 작업을 수행할 수 있습니다.

함수는 HTTP 응답을 전송해야 합니다. 함수가 백그라운드 태스크(예: 스레드, 기능, 자바스크립트 Promise 객체, 콜백 또는 시스템 프로세스)를 만드는 경우 이를 종료하거나 HTTP 응답을 전송하기 전 태스크를 해결해야 합니다. HTTP 응답이 전송되기 전 종료되지 않은 태스크는 완료되지 않을 수 있고 정의되지 않은 동작을 일으킬 수 있습니다.

HTTP 함수 및 관련 옵션에 대한 자세한 내용은 HTTP 트리거를 참조하세요.

CORS 처리

교차 출처 리소스 공유(CORS)는 한 도메인에서 실행되는 애플리케이션이 다른 도메인의 리소스에 액세스하도록 허용하는 한 가지 방법입니다. 예를 들어 사용자 도메인이 함수 액세스를 위해 Cloud Run Functions 도메인에 요청을 수행하도록 허용해야 할 수 있습니다.

CORS가 올바르게 설정되지 않은 경우 다음과 같은 오류가 표시될 수 있습니다.

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.

함수에 교차 출처 요청을 허용하려면 Access-Control-Allow-Origin 헤더를 HTTP 응답에 따라 적합하게 설정합니다. 프리플라이트된 교차 출처 요청의 경우 204 응답 코드 및 추가 헤더로 프리플라이트 OPTIONS 요청에 응답해야 합니다.

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

자바


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 제한사항

프리플라이트된 교차 출처 요청의 경우 프리플라이트 OPTIONS 요청이 Authorization 헤더 없이 전송되므로, 인증이 필요한 모든 HTTP 함수에서 거부됩니다. 프리플라이트 요청이 실패하기 때문에 기본 요청도 실패합니다. 이 제한사항을 해결하려면 다음 옵션 중 하나를 사용합니다.

다음 단계