Module: Belt::LambdaHandler

Includes:
Helpers::Response
Defined in:
lib/belt/lambda_handler.rb

Overview

Lambda handler module — include in your Lambda entry point to get automatic observability setup, CORS preflight handling, JSON body parsing, and error wrapping.

Usage:

require "belt"

include Belt::LambdaHandler

def execute(path:, body:, event:)
  ROUTER.route(event: event, body: body)
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers::Response

#cors_headers, #error_response, #handle_error_and_respond, #html_response, #success_response

Instance Attribute Details

#loggerObject

Returns the value of attribute logger.



24
25
26
# File 'lib/belt/lambda_handler.rb', line 24

def logger
  @logger
end

#metricsObject

Returns the value of attribute metrics.



24
25
26
# File 'lib/belt/lambda_handler.rb', line 24

def metrics
  @metrics
end

Class Method Details

.included(base) ⇒ Object



26
27
28
# File 'lib/belt/lambda_handler.rb', line 26

def self.included(base)
  base.instance_variable_set(:@belt_lambda_handler_included, true)
end

Instance Method Details

#lambda_handler(event:, context:) ⇒ Object

API Gateway Lambda handler. Handles HTTP requests with automatic CORS, body parsing, observability, and error wrapping. Override ‘execute` to provide your own routing logic.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/belt/lambda_handler.rb', line 33

def lambda_handler(event:, context:)
  init_observability(context: context)

  LambdaLoadout.with_logging_and_metrics(
    logger,
    metrics,
    context,
    event: event,
    error_notification_config: {
      sns_topic_arn: ENV.fetch('ERROR_NOTIFICATION_TOPIC_ARN', nil)
    }
  ) do
    logger.info('Lambda invoked',
                http_method: event['httpMethod'],
                path: event['path'],
                source_ip: event.dig('requestContext', 'identity', 'sourceIp'))

    return { statusCode: 200, headers: cors_headers(event), body: '{}' } if event['httpMethod'] == 'OPTIONS'

    begin
      body = JSON.parse(event['body'] || '{}')
    rescue JSON::ParserError
      return error_response('Invalid JSON in request body')
    end

    begin
      result = execute(path: event['path'], body: body, event: event)
      logger.info('Request completed', status_code: result[:statusCode], path: event['path'])
      result
    rescue StandardError => e
      handle_error_and_respond(e, 'Unhandled error during request processing',
                               { path: event['path'], method: event['httpMethod'] })
    end
  end
rescue StandardError => e
  Belt::Helpers::ErrorLogging.log_error(@logger, 'Unhandled Lambda error', e,
                                        { phase: 'lambda_handler', path: event&.dig('path') })

  body = { error: 'Internal server error' }
  if verbose_errors_enabled?
    body[:message] = e.message
    body[:type] = e.class.name
    body[:backtrace] = Belt::Helpers::ErrorLogging.filter_backtrace(e.backtrace || [])
  end

  { statusCode: 500, headers: cors_headers, body: JSON.generate(body) }
end