首頁 > 後端開發 > Golang > 主體

如何在 go 中為 lambda 中間件建立泛型類型

WBOY
發布: 2024-02-06 09:35:11
轉載
520 人瀏覽過

如何在 go 中为 lambda 中间件创建泛型类型

問題內容

我正在 aws lambda 中使用 go 並尋找通用的中間件解決方案。我有以下程式碼:

func wshandler(ctx context.context, event events.apigatewaywebsocketproxyrequest) (events.apigatewayproxyresponse, error) {
}

type handlerfunc func(context.context, events.apigatewaywebsocketproxyrequest) (events.apigatewayproxyresponse, error)

func logmiddleware(next handlerfunc) handlerfunc {
    return handlerfunc(func(ctx context.context, event events.apigatewaywebsocketproxyrequest) (events.apigatewayproxyresponse, error) {
        
        return next(ctx, event)
    })
}

lambda.start(logmiddleware(wshandler))
登入後複製

中間件函數有一個參數 events.apigatewaywebsocketproxyrequest 因為目標處理程序 wshandler 使用此類型。

我有另一個處理程序,它採用參數 event events.apigatewayproxyrequest ,如下所示。由於參數不匹配,因此無法使用此中間件。

graphqlquerymutationhandler(ctx context.context, event events.apigatewayproxyrequest){
...
}
登入後複製

我嘗試將中間件句柄更改為 interface{},但不起作用。 go 抱怨這種類型。

type HandlerFunc func(context.Context, interface{}) (interface{}, error)
登入後複製

有沒有辦法讓中間件適用於任何處理程序類型?


正確答案


讓我分享我能夠在我的系統上複製的工作解決方案。首先跟大家分享我使用的專案佈局:

events/
  http_event.json
  sqs_event.json
hello-world/
  main.go
sqs/
  main.go
middlewares/
  middlewares.go
登入後複製

現在,讓我們專注於程式碼。

middlewares/middlewares.go

#程式碼如下:

package middlewares

import (
    "context"
    "fmt"

    "github.com/aws/aws-lambda-go/events"
)

type record struct {
    events.apigatewayproxyrequest `json:",omitempty"`
    events.sqsevent               `json:",omitempty"`
}

type event struct {
    records []record `json:"records"`
}

type handlerfunc func(ctx context.context, event event) (string, error)

func logmiddleware(ctx context.context, next handlerfunc) handlerfunc {
    return handlerfunc(func(ctx context.context, event event) (string, error) {
        fmt.println("log from middleware!")
        return next(ctx, event)
    })
}
登入後複製

讓我們總結一下基本概念:

  • 我們定義 event 結構體,它將成為我們的通用事件。它是 record 結構的包裝器。
  • record 結構體使用結構嵌入來嵌入我們要處理的所有事件(例如 event.apigatewayproxyrequestsqsevent)。
  • 我們依靠中間件簽名中的這一點來盡可能通用。

events/http_event.json

#
{
    "records": [
        {
            "body": "{\"message\": \"hello world\"}",
            "resource": "/hello",
            "path": "/hello",
            "httpmethod": "get",
            "isbase64encoded": false,
            "querystringparameters": {
                "foo": "bar"
            },
            "pathparameters": {
                "proxy": "/path/to/resource"
            },
            "stagevariables": {
                "baz": "qux"
            },
            "headers": {
                "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                "accept-encoding": "gzip, deflate, sdch",
                "accept-language": "en-us,en;q=0.8",
                "cache-control": "max-age=0",
                "cloudfront-forwarded-proto": "https",
                "cloudfront-is-desktop-viewer": "true",
                "cloudfront-is-mobile-viewer": "false",
                "cloudfront-is-smarttv-viewer": "false",
                "cloudfront-is-tablet-viewer": "false",
                "cloudfront-viewer-country": "us",
                "host": "1234567890.execute-api.us-east-1.amazonaws.com",
                "upgrade-insecure-requests": "1",
                "user-agent": "custom user agent string",
                "via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (cloudfront)",
                "x-amz-cf-id": "cdehvqoznx43vyqb9j2-nvch-9z396uhbp027y2jvkcpnlmgjhqlaa==",
                "x-forwarded-for": "127.0.0.1, 127.0.0.2",
                "x-forwarded-port": "443",
                "x-forwarded-proto": "https"
            },
            "requestcontext": {
                "accountid": "123456789012",
                "resourceid": "123456",
                "stage": "prod",
                "requestid": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
                "requesttime": "09/apr/2015:12:34:56 +0000",
                "requesttimeepoch": 1428582896000,
                "identity": {
                    "cognitoidentitypoolid": null,
                    "accountid": null,
                    "cognitoidentityid": null,
                    "caller": null,
                    "accesskey": null,
                    "sourceip": "127.0.0.1",
                    "cognitoauthenticationtype": null,
                    "cognitoauthenticationprovider": null,
                    "userarn": null,
                    "useragent": "custom user agent string",
                    "user": null
                },
                "path": "/prod/hello",
                "resourcepath": "/hello",
                "httpmethod": "get",
                "apiid": "1234567890",
                "protocol": "http/1.1"
            }
        }
    ]
}
登入後複製

這裡沒什麼好說的。

events/sqs_event.json

#
{
    "records": [
        {
            "records": [
                {
                    "messageid": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
                    "receipthandle": "messagereceipthandle",
                    "body": "my own event payload!",
                    "attributes": {
                        "approximatereceivecount": "1",
                        "senttimestamp": "1523232000000",
                        "senderid": "123456789012",
                        "approximatefirstreceivetimestamp": "1523232000001"
                    },
                    "messageattributes": {},
                    "md5ofbody": "4d1d0024b51659ad8c3725f9ba7e2471",
                    "eventsource": "aws:sqs",
                    "eventsourcearn": "arn:aws:sqs:us-east-1:123456789012:myqueue",
                    "awsregion": "us-east-1"
                }
            ]
        }
    ]
}
登入後複製

這也適用於這裡。

hello-world/main.go

package main

import (
    "context"
    "fmt"

    "httplambda/middlewares"

    "github.com/aws/aws-lambda-go/lambda"
)

func lambdahandler(ctx context.context, event middlewares.event) (string, error) {
    _ = ctx
    fmt.println("path:", event.records[0].apigatewayproxyrequest.path)

    fmt.println("hi from http-triggered lambda!")

    return "", nil
}

func main() {
    // start the lambda handler
    lambda.start(middlewares.logmiddleware(context.background(), lambdahandler))
}
登入後複製

請注意我們如何取得活動資訊。

sqs/main.go

package main

import (
    "context"
    "fmt"

    "httplambda/middlewares"

    "github.com/aws/aws-lambda-go/lambda"
)

func lambdaHandler(ctx context.Context, event middlewares.Event) (string, error) {
    _ = ctx
    fmt.Println("Queue name:", event.Records[0].SQSEvent.Records[0].EventSourceARN)
    fmt.Println("Hi from SQS-triggered lambda!")
    return "", nil
}

func main() {
    lambda.Start(middlewares.LogMiddleware(context.Background(), lambdaHandler))
}
登入後複製

決賽

有幾個注意事項要考慮:

  1. 在遵循此解決方案之前,我嘗試使用類型參數,但沒有成功。中間件的簽名中似乎不允許使用它們。
  2. 程式碼過於簡化,尚未做好生產準備。

如果這有幫助或您需要其他任何東西,請告訴我,謝謝!

以上是如何在 go 中為 lambda 中間件建立泛型類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板