- vừa được xem lúc

[Golang] AWS Lambda thông qua Serverless Framework - Phần 2

0 0 33

Người đăng: Open Dev

Theo Viblo Asia

Mục Tiêu:

  • Nhận request data từ client thông qua api-gateway
  • Response data về cho client thông qua api-gateway
  • Cấu hình đơn giản như: timeout, memory, environment,...

Chuẩn Bị:

  • Để tiếp tục đọc và hiểu những phần sau, cần phải có một lambda function được tạo trước đó.
  • Nếu bạn chưa tạo một lambda function thì tham khảo here để hiểu các phần sau.

Giải Quyết Vấn Đề

1. Nhận request data:

  • http body có dạng.
{ "request_id":"123123213", "data": { "name":"open dev" }
}
  • Trong lambda muốn get data từ client, thì sử dụng api-gateway events APIGatewayProxyRequest. Struct này là của aws-sdk trong struct chỉ cần quan tâm field Body và dùng json.Unmarshal
// APIGatewayProxyRequest contains data coming from the API Gateway proxy
type APIGatewayProxyRequest struct { Resource string `json:"resource"` // The resource path defined in API Gateway Path string `json:"path"` // The url path for the caller HTTPMethod string `json:"httpMethod"` Headers map[string]string `json:"headers"` MultiValueHeaders map[string][]string `json:"multiValueHeaders"` QueryStringParameters map[string]string `json:"queryStringParameters"` MultiValueQueryStringParameters map[string][]string `json:"multiValueQueryStringParameters"` PathParameters map[string]string `json:"pathParameters"` StageVariables map[string]string `json:"stageVariables"` RequestContext APIGatewayProxyRequestContext `json:"requestContext"` Body string `json:"body"` IsBase64Encoded bool `json:"isBase64Encoded,omitempty"`
}
  • Khai báo một struct để unmarshal data
type RequestBodyAPIGW struct { RequestID string `json:"request_id"` Data interface{} `json:"data"`
}
  • Unmarshal data:
json.Unmarshal([]byte(eventReq.Body), &req)

2. Response data:

  • client muốn response có format. Trong đó field data thì trả về dữ liệu giống với request truyền vào.
{ "data": { "name": "open dev" }, "responseId": "123123213", "responseMessage": "successfully", "responseTime": "2022-12-17T03:53:42.325+00:00"
}
  • Để lambda return data, thì cũng sử dụng api-gateway events APIGatewayProxyResponse.
// APIGatewayProxyResponse configures the response to be returned by API Gateway for the request
type APIGatewayProxyResponse struct { StatusCode int `json:"statusCode"` Headers map[string]string `json:"headers"` MultiValueHeaders map[string][]string `json:"multiValueHeaders"` Body string `json:"body"` IsBase64Encoded bool `json:"isBase64Encoded,omitempty"`
}
  • Thông thường response sẽ có 2 dạng, api xảy ra error hoặc không. Mình viết 2 hàm response và gắn vào field Body.
type HttpResponse struct { Uuid string // uuid, indicator per api Err error Time string // time tracing Data interface{}
} func responseOk(respBody HttpResponse) string { var buf bytes.Buffer mapRes := map[string]interface{}{ "responseId": respBody.Uuid, "responseMessage": "successfully", "responseTime": respBody.Time, } if respBody.Data != nil { mapRes["data"] = respBody.Data } body, errMarshal := json.Marshal(mapRes) if errMarshal != nil { log.Default().Println("marshal response err", errMarshal) } json.HTMLEscape(&buf, body) return buf.String()
} func responseErr(respBody HttpResponse) string { var buf bytes.Buffer mapRes := map[string]interface{}{ "responseId": respBody.Uuid, "responseMessage": respBody.Err.Error(), "responseTime": respBody.Time, } body, errMarshal := json.Marshal(mapRes) if errMarshal != nil { log.Default().Println("marshal response err", errMarshal) } json.HTMLEscape(&buf, body) return buf.String()
}

3. Cấu hình timeout, memory, env:

  • Để cấu hình 3 thuộc tính trên, đơn giản chỉ cần mở file serverless.yml.
  • Trong block provider: ta time 2 field timeoutmemorySize, thì đã set được timeout và resource.
provider: timeout: 6 memorySize: 256
  • Environment của lambda, cũng tương tự trong block provider:, thêm environment: trong lambda sẽ có env env_test có giá trị là value-test
provider: environment: env_test: "value-test"

Deploy Function:

  • file Makefile:
build: env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -o bin/hello hello/main.go
clean: rm -rf ./bin
deploy: clean build sls deploy --verbose
  • run:
make deploy
  • output:

Test:

Full source:

  • file golang:
package main import ( "bytes" "context" "encoding/json" "log" "time" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda"
) type Response events.APIGatewayProxyResponse type RequestBodyAPIGW struct { RequestID string `json:"requestId"` Data interface{} `json:"data"`
} // type ResponseBodyAPIGW struct {
// RequestID string `json:"request_id"`
// Message string `json:"message"`
// } func Handler(ctx context.Context, eventReq events.APIGatewayProxyRequest) (Response, error) { var ( req = RequestBodyAPIGW{} resp = Response{ StatusCode: 404, IsBase64Encoded: false, Headers: map[string]string{ "Content-Type": "application/json", "X-MyCompany-Func-Reply": "hello-handler", }, } ) err := json.Unmarshal([]byte(eventReq.Body), &req) if err != nil { resp.Body = ParseResponse(HttpResponse{ Uuid: req.RequestID, Err: err}) return resp, nil } resp.StatusCode = 200 resp.Body = ParseResponse(HttpResponse{Uuid: req.RequestID, Data: req.Data}) return resp, nil
} func main() { lambda.Start(Handler)
} type HttpResponse struct { Uuid string // uuid, indicator per api Err error Time string // time tracing Data interface{}
} func ParseResponse(respBody HttpResponse) string { respBody.Time = time.Now().Format("2006-01-02T15:04:05.000-07:00") if respBody.Err != nil { return responseErr(respBody) } return responseOk(respBody)
} func responseOk(respBody HttpResponse) string { var buf bytes.Buffer mapRes := map[string]interface{}{ "responseId": respBody.Uuid, "responseMessage": "successfully", "responseTime": respBody.Time, } if respBody.Data != nil { mapRes["data"] = respBody.Data } body, errMarshal := json.Marshal(mapRes) if errMarshal != nil { log.Default().Println("marshal response err", errMarshal) } json.HTMLEscape(&buf, body) return buf.String()
} func responseErr(respBody HttpResponse) string { var buf bytes.Buffer mapRes := map[string]interface{}{ "responseId": respBody.Uuid, "responseMessage": respBody.Err.Error(), "responseTime": respBody.Time, } body, errMarshal := json.Marshal(mapRes) if errMarshal != nil { log.Default().Println("marshal response err", errMarshal) } json.HTMLEscape(&buf, body) return buf.String()
}
  • file serverless.yml
service: lambda-go
frameworkVersion: '3' provider: name: aws runtime: go1.x timeout: 6 memorySize: 256 environment: env_test: "value-test" package: patterns: - '!./**' - ./bin/** functions: hello: handler: bin/hello events: - httpApi: path: /hello method: post

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 131

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 56

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 60

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 237

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 54