function.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2. package lambda
  3. import (
  4. "context"
  5. "encoding/json"
  6. "reflect"
  7. "time"
  8. "github.com/aws/aws-lambda-go/lambda/messages"
  9. "github.com/aws/aws-lambda-go/lambdacontext"
  10. )
  11. type Function struct {
  12. handler Handler
  13. }
  14. func (fn *Function) Ping(req *messages.PingRequest, response *messages.PingResponse) error {
  15. *response = messages.PingResponse{}
  16. return nil
  17. }
  18. func (fn *Function) Invoke(req *messages.InvokeRequest, response *messages.InvokeResponse) error {
  19. defer func() {
  20. if err := recover(); err != nil {
  21. panicInfo := getPanicInfo(err)
  22. response.Error = &messages.InvokeResponse_Error{
  23. Message: panicInfo.Message,
  24. Type: getErrorType(err),
  25. StackTrace: panicInfo.StackTrace,
  26. ShouldExit: true,
  27. }
  28. }
  29. }()
  30. deadline := time.Unix(req.Deadline.Seconds, req.Deadline.Nanos).UTC()
  31. invokeContext, cancel := context.WithDeadline(context.Background(), deadline)
  32. defer cancel()
  33. lc := &lambdacontext.LambdaContext{
  34. AwsRequestID: req.RequestId,
  35. InvokedFunctionArn: req.InvokedFunctionArn,
  36. Identity: lambdacontext.CognitoIdentity{
  37. CognitoIdentityID: req.CognitoIdentityId,
  38. CognitoIdentityPoolID: req.CognitoIdentityPoolId,
  39. },
  40. }
  41. if len(req.ClientContext) > 0 {
  42. if err := json.Unmarshal(req.ClientContext, &lc.ClientContext); err != nil {
  43. response.Error = lambdaErrorResponse(err)
  44. return nil
  45. }
  46. }
  47. invokeContext = lambdacontext.NewContext(invokeContext, lc)
  48. invokeContext = context.WithValue(invokeContext, "x-amzn-trace-id", req.XAmznTraceId)
  49. payload, err := fn.handler.Invoke(invokeContext, req.Payload)
  50. if err != nil {
  51. response.Error = lambdaErrorResponse(err)
  52. return nil
  53. }
  54. response.Payload = payload
  55. return nil
  56. }
  57. func getErrorType(err interface{}) string {
  58. errorType := reflect.TypeOf(err)
  59. if errorType.Kind() == reflect.Ptr {
  60. return errorType.Elem().Name()
  61. }
  62. return errorType.Name()
  63. }
  64. func lambdaErrorResponse(invokeError error) *messages.InvokeResponse_Error {
  65. var errorName string
  66. if errorType := reflect.TypeOf(invokeError); errorType.Kind() == reflect.Ptr {
  67. errorName = errorType.Elem().Name()
  68. } else {
  69. errorName = errorType.Name()
  70. }
  71. return &messages.InvokeResponse_Error{
  72. Message: invokeError.Error(),
  73. Type: errorName,
  74. }
  75. }