編寫 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 適用的 Functions Framework 註冊 HTTP 處理常式函式。HTTP 處理常式函式須為 Express 中介軟體函式,可接受要求和回應引數,並傳送 HTTP 回應。
Cloud Run functions 會根據要求的 Content-Type 標頭,使用 body-parser 自動剖析要求主體,因此您可以在 HTTP 處理常式中存取 req.body 和 req.rawBody 物件。
函式進入點是向 Functions Framework 註冊的處理常式名稱。在這個範例中,進入點為 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 中,您可以使用 Python 適用的 Functions Framework 註冊 HTTP 處理常式函式。HTTP 處理常式函式必須接受 Flask 要求物件做為引數,並傳回 Flask 可轉換為 HTTP 回應物件的值。
函式進入點是向 Functions Framework 註冊的處理常式函式名稱。在這個範例中,進入點為 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 適用的 Functions Framework 註冊 HTTP 處理常式函式。HTTP 處理常式函式必須透過標準 http.HandlerFunc 介面傳送 HTTP 回應。
函式進入點是向 Functions Framework 註冊的處理常式名稱。在這個範例中,進入點為 MyHTTPFunction。
HTTP 處理常式函式必須實作標準 http.HandlerFunc 介面,可接受 http.ResponseWriter 介面,您的函式會使用這個介面建立要求的回應,以及指向 http.Request struct 的指標,其中包含傳入 HTTP 要求的詳細資料。
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");
}
}
在 Java 中,您可以使用 Functions Framework Java API,透過 HttpFunction 介面實作 HTTP 處理常式類別。service() 方法必須傳送 HTTP 回應。
函式進入點是 HTTP 處理常式類別的完整名稱,包括套件名稱。在這個範例中,進入點為 myhttpfunction.MyHttpFunction。
service 方法會收到 HttpRequest 物件,說明傳入的 HTTP 要求,以及函式會填入回應訊息的 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 適用的 Functions Framework,透過 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 適用的 Functions Framework 註冊 HTTP 處理常式函式。HTTP 處理常式函式必須接受 Rack 要求物件做為引數,並傳回可用做 HTTP 回應的值。
函式進入點是向 Functions Framework 註冊的處理常式名稱。在這個範例中,進入點為 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 適用的 Functions Framework 註冊 HTTP 處理常式函式。HTTP 處理常式函式必須接受實作 PSR-7 ServerRequestInterface 介面的引數,且須以字串或實作 PSR-7 ResponseInterface 介面的物件形式傳回 HTTP 回應。
函式進入點是向 Functions Framework 註冊的處理常式名稱。在這個範例中,進入點為 myHttpFunction。
HTTP 要求和回應
HTTP 函式接受「HTTP 觸發條件」頁面所列出的 HTTP 要求方法。HTTP 處理常式可以檢查要求方法,並根據方法執行不同的動作。
函式必須傳送 HTTP 回應。如果函式會建立背景任務 (例如使用執行緒、future、JavaScript 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.
如要允許對函式提出跨來源要求,請在 HTTP 回應上設定適當的 Access-Control-Allow-Origin 標頭。如果是預檢跨來源要求,須以 204 回應代碼和額外標頭回應預檢 OPTIONS 要求。
Node.js
Python
Go
Java
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
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 函式中遭到拒絕。由於預檢要求失敗,主要求也會失敗。如要避開這項限制,請採取下列任一做法:
- 允許在未經驗證的情況下叫用函式。
- 在同一個網域上託管網頁應用程式和 Cloud Run 函式,避免發生 CORS 問題。此做法需整合 Firebase 託管與 Cloud Run functions。
後續步驟
- 進一步瞭解 HTTP 觸發條件。
- 瞭解如何部署 Cloud Run 函式。