您可以使用Go请求处理程序响应接收到的事件并执行相应的业务逻辑。本文介绍Go请求处理程序的相关概念、结构特点和使用示例。
如您需要通过HTTP触发器或自定义域名访问函数,请先获取请求结构体再自定义HTTP响应。更多信息,请参见HTTP触发器调用函数。
什么是请求处理程序
FC函数的请求处理程序,是函数代码中处理请求的方法。当您的FC函数被调用时,函数计算会运行您提供的Handler方法处理请求。您可以通过函数计算控制台的函数入口配置Handler。
对Go语言的FC函数而言,您的请求处理程序被编译为一个可执行的二进制文件。您只需要将FC函数的请求处理程序配置项设置为该可执行文件的文件名即可。
关于FC函数的具体定义和相关操作,请参见创建事件函数。
请求处理程序的具体配置均需符合函数计算平台的配置规范。配置规范因请求处理程序类型而异。
使用示例
在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
:需要引用函数计算依赖的包,主要包括以下包:github.com/aliyun/fc-runtime-go-sdk/fc
:函数计算Go语言的核心库。context
:函数计算Go语言的Context对象。
func HandleRequest(ctx context.Context, event StructEvent) (string, error)
:处理请求的方法(即Handler),需包含将要执行的代码,参数含义如下:func main()
:运行FC函数代码的入口点,Go程序必须包含main
函数。通过添加代码fc.Start(HandleRequest)
,您的程序即可运行在阿里云函数计算平台。
Event Handler签名
下面列举出了有效的Event Handler签名,其中InputType
和OutputType
与encoding/json
标准库兼容。
函数计算会使用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示例代码:
event-struct.go:
event
为Struct类型的示例代码。event-string.go:
event
为String类型的示例代码。event-map.go:
event
为map[string]interface{}
类型的示例代码。
更多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触发。
操作步骤
登录函数计算控制台,在左侧导航栏,单击函数。
在顶部菜单栏,选择地域,然后在函数页面,单击目标函数。
在函数详情页面,单击配置页签,然后再左侧导航栏,单击触发器,在触发器页面获取HTTP触发器的公网访问地址。
执行以下命令调用函数。
curl -i "https://http-trigger-demo.cn-shanghai.fcapp.run" -d "Hello FC!"
错误处理
本示例代码支持使用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)
}