您可以使用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 () errorfunc (InputType) errorfunc () (OutputType, error)func (InputType) (OutputType, error)func (context.Context) errorfunc (context.Context, InputType) errorfunc (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触发器的公网访问地址。
执行以下命令调用函数。
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)
}