全部產品
Search
文件中心

Function Compute:請求處理常式(Handler)

更新時間:Sep 27, 2024

您可以使用Go請求處理常式響應接收到的事件並執行相應的商務邏輯。本文介紹Go請求處理常式的相關概念、結構特點和使用樣本。

說明

如您需要通過HTTP觸發器或自訂網域名訪問函數,請先擷取請求結構體再自訂HTTP響應。更多資訊,請參見HTTP觸發器調用函數

什麼是請求處理常式

FC函數的請求處理常式,是函數代碼中處理請求的方法。當您的FC函數被調用時,Function Compute會運行您提供的Handler方法處理請求。您可以通過Function Compute控制台函數入口配置Handler。

對Go語言的FC函數而言,您的請求處理常式被編譯為一個可執行檔二進位檔案。您只需要將FC函數的請求處理常式配置項設定為該可執行檔的檔案名稱即可。

關於FC函數的具體定義和相關操作,請參見建立事件函數

請求處理常式的具體配置均需符合Function Compute平台的配置規範。配置規範因請求處理常式類型而異。

使用樣本

在Go語言的代碼中,您需要引入官方的SDK庫aliyun/serverless/fc-runtime-go-sdk/fc,並實現handler函數和main函數。樣本如下。

package main

import (
    "fmt"
    "context"

    "github.com/aliyun/fc-runtime-go-sdk/fc"
)

type StructEvent struct {
    Key string `json:"key"`
}

func HandleRequest(ctx context.Context, event StructEvent) (string, error) {
    return fmt.Sprintf("hello, %s!", event.Key), nil
}

func main() {
    fc.Start(HandleRequest)
}

傳入的event參數是一個包含key屬性的JSON字串,樣本如下。

{
  "key": "value"
}

具體的樣本解析如下:

  • package main:在Go語言中,Go應用程式都包含一個名為main的包。

  • import:需要引用Function Compute依賴的包,主要包括以下包:

    • github.com/aliyun/fc-runtime-go-sdk/fcFunction ComputeGo語言的核心庫。

    • contextFunction ComputeGo語言的Context對象。

  • func HandleRequest(ctx context.Context, event StructEvent) (string, error):處理請求的方法(即Handler),需包含將要執行的代碼,參數含義如下:

    • ctx context.Context:為您的FC函數調用提供在調用時的運行上下文資訊。更多資訊,請參見上下文

    • event StructEvent:調用函數時傳入的資料,可以支援多種類型。

    • string, error:返回兩個值,字串和錯誤資訊。更多資訊,請參見錯誤處理

    • return fmt.Sprintf("Hi,%s !", event.Key), nil:簡單地返回hello資訊,其中包含傳入的eventnil表示沒有報錯。

  • func main():運行FC函數代碼的進入點,Go程式必須包含main函數。通過添加代碼fc.Start(HandleRequest),您的程式即可運行在阿里雲Function Compute平台。

Event Handler簽名

下面列舉出了有效Event Handler簽名,其中InputTypeOutputTypeencoding/json標準庫相容。

Function Compute會使用json.Unmarshal方法對傳入的InputType進行還原序列化,以及使用json.Marshal方法對返回的OutputType進行序列化。關於如何還原序列化函數的返回資料,請參考JSON Unmarshal

  • func ()

  • func () error

  • func (InputType) error

  • func () (OutputType, error)

  • func (InputType) (OutputType, error)

  • func (context.Context) error

  • func (context.Context, InputType) error

  • func (context.Context) (OutputType, error)

  • func (context.Context, InputType) (OutputType, error)

Handler的使用需遵循以下規則:

  • Handler必須是一個函數。

  • Handler支援0~2個輸入參數。如果有2個參數,則第一個參數必須是context.Context

  • Handler支援0~2個傳回值。如果有1個傳回值,則必須是error類型;如果有2個傳回值,則第2個傳回值必須是error

函數的Handler範例程式碼:

更多Handler樣本,請參見examples

Context

Context的詳細使用方法,請參見上下文

使用HTTP觸發器調用函數

範例程式碼

package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/aliyun/fc-runtime-go-sdk/events"
	"github.com/aliyun/fc-runtime-go-sdk/fc"
)

type HTTPTriggerEvent events.HTTPTriggerEvent
type HTTPTriggerResponse events.HTTPTriggerResponse

func (h HTTPTriggerEvent) String() string {
	jsonBytes, err := json.MarshalIndent(h, "", "  ")
	if err != nil {
		return ""
	}
	return string(jsonBytes)
}

func NewHTTPTriggerResponse(statusCode int) *HTTPTriggerResponse {
	return &HTTPTriggerResponse{StatusCode: statusCode}
}

func (h *HTTPTriggerResponse) String() string {
	jsonBytes, err := json.MarshalIndent(h, "", "  ")
	if err != nil {
		return ""
	}
	return string(jsonBytes)
}

func (h *HTTPTriggerResponse) WithStatusCode(statusCode int) *HTTPTriggerResponse {
	h.StatusCode = statusCode
	return h
}

func (h *HTTPTriggerResponse) WithHeaders(headers map[string]string) *HTTPTriggerResponse {
	h.Headers = headers
	return h
}

func (h *HTTPTriggerResponse) WithIsBase64Encoded(isBase64Encoded bool) *HTTPTriggerResponse {
	h.IsBase64Encoded = isBase64Encoded
	return h
}

func (h *HTTPTriggerResponse) WithBody(body string) *HTTPTriggerResponse {
	h.Body = body
	return h
}

func HandleRequest(event HTTPTriggerEvent) (*HTTPTriggerResponse, error) {
	fmt.Printf("event: %v\n", event)
	if event.Body == nil {
		return NewHTTPTriggerResponse(http.StatusBadRequest).
			WithBody(fmt.Sprintf("the request did not come from an HTTP Trigger, event: %v", event)), nil
	}

	reqBody := *event.Body
	if event.IsBase64Encoded != nil && *event.IsBase64Encoded {
		decodedByte, err := base64.StdEncoding.DecodeString(*event.Body)
		if err != nil {
			return NewHTTPTriggerResponse(http.StatusBadRequest).
				WithBody(fmt.Sprintf("HTTP Trigger body is not base64 encoded, err: %v", err)), nil
		}
		reqBody = string(decodedByte)
	}
	return NewHTTPTriggerResponse(http.StatusOK).WithBody(reqBody), nil
}

func main() {
	fc.Start(HandleRequest)
}

上述樣本從SDK中引入了HTTP觸發器的請求結構HTTPTriggerEvent,以及響應結構HTTPTriggerResponse。關於HTTP觸發調用的請求負載格式和響應負載格式,請參見HTTP觸發器調用函數

前提條件

已使用上述樣本建立運行環境為Go的函數,並建立HTTP觸發器。具體操作,請參見建立事件函數配置HTTP觸發器並使用HTTP觸發

操作步驟

  1. 登入Function Compute控制台,在左側導覽列,單擊函數

  2. 在頂部功能表列,選擇地區,然後在函數頁面,單擊目標函數。

  3. 在函數詳情頁面,單擊配置頁簽,然後再左側導覽列,單擊觸發器,在觸發器頁面擷取HTTP觸發器的公網訪問地址。

  4. 執行以下命令調用函數。

    curl -i "https://http-trigger-demo.cn-shanghai.fcapp.run" -d "Hello FC!"
    重要
    • 如果HTTP觸發器的認證方式無需認證,您可以直接使用Postman或Curl工具來調用函數。具體操作,請參見本文操作步驟

    • 如果HTTP觸發器的認證方式為簽名認證或JWT認證,請使用簽名方式或JWT認證方式來調用函數。具體操作,請參見認證鑒權

錯誤處理

本範例程式碼支援使用HTTP Trigger觸發器或者自訂網域名調用,如果使用API調用,但配置的測試參數不符合HTTP Trigger請求格式規範,會出現報錯。

例如,在控制台上調用,配置請求參數為"Hello, FC!",點擊測試函數按鈕,會出現報錯如下所示。

{
    "statusCode": 400,
    "body": "the request did not come from an HTTP Trigger, event: {\n  \"version\": null,\n  \"rawPath\": null,\n  \"headers\": null,\n  \"queryParameters\": null,\n  \"body\": null,\n  \"isBase64Encoded\": null,\n  \"requestContext\": null\n}"
}

如果想擷取原始的請求事件裝載,可以使用下面樣本中的Handler。

// GetRawRequestEvent: obtain the raw request event
func GetRawRequestEvent(event []byte) (*HTTPTriggerResponse, error) {
	fmt.Printf("raw event: %s\n", string(event))
	return NewHTTPTriggerResponse(http.StatusOK).WithBody(string(event)), nil
}

func main() {
	fc.Start(GetRawRequestEvent)
}