Class: Jets::Controller::Base

Inherits:
Lambda::Functions show all
Includes:
ActiveSupport::Rescuable, Authorization, Callbacks, Cookies, ForgeryProtection, Layout, Params, Rendering, Router::Helpers
Defined in:
lib/jets/controller/base.rb

Constant Summary

Constants included from Router::Helpers::CoreHelper

Router::Helpers::CoreHelper::CONTROLLER_DELEGATES

Instance Attribute Summary collapse

Attributes inherited from Lambda::Functions

#context, #event, #meth

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Rendering

#actual_host, #add_stage, #adjust_content_type!, #default_layout, #ensure_render, #managed_options, #normalize_options, #render, #url_for

Methods included from Redirection

#ensure_protocol, #redirect_back, #redirect_to

Methods included from Params

#body_params, #filtered_parameters, #params, #path_params, #query_params, #request_params, #unescape_recursively

Methods included from Router::Helpers::NamedRoutesHelper

clear!

Methods included from Router::Helpers::CoreHelper

#polymorphic_path

Methods included from ForgeryProtection

#verify_authenticity_token

Methods included from Cookies

#cookies

Methods inherited from Lambda::Functions

inherited, output_keys, subclasses

Methods included from Lambda::Dsl

#lambda_functions

Constructor Details

#initialize(event, context = {}, meth) ⇒ Base

Returns a new instance of Base.



21
22
23
24
25
# File 'lib/jets/controller/base.rb', line 21

def initialize(event, context={}, meth)
  super
  @request = Request.new(event, context)
  @response = Response.new
end

Instance Attribute Details

#requestObject (readonly)

Returns the value of attribute request.



19
20
21
# File 'lib/jets/controller/base.rb', line 19

def request
  @request
end

#responseObject (readonly)

Returns the value of attribute response.



19
20
21
# File 'lib/jets/controller/base.rb', line 19

def response
  @response
end

#sessionObject

Returns the value of attribute session.



20
21
22
# File 'lib/jets/controller/base.rb', line 20

def session
  @session
end

Class Method Details

.helper_method(*meths) ⇒ Object



188
189
190
191
192
# File 'lib/jets/controller/base.rb', line 188

def helper_method(*meths)
  meths.each do |meth|
    Jets::Router::Helpers.define_helper_method(meth)
  end
end

.internal(value = nil) ⇒ Object



180
181
182
183
184
185
186
# File 'lib/jets/controller/base.rb', line 180

def internal(value=nil)
  if !value.nil?
    self.internal_controller = value
  else
    self.internal_controller
  end
end

.process(event, context = {}, meth) ⇒ Object

Overrides Base.process



28
29
30
31
32
33
34
35
36
# File 'lib/jets/controller/base.rb', line 28

def self.process(event, context={}, meth)
  controller = new(event, context, meth)
  # Using send because process! is private method in Jets::RackController so
  # it doesnt create a lambda function.  It's doesnt matter what scope process!
  # is in Controller::Base because Jets lambda functions inheritance doesnt
  # include methods in Controller::Base.
  # TODO: Can process! be a protected method to avoid this?
  controller.send(:process!)
end

Instance Method Details

#action_nameObject



174
175
176
# File 'lib/jets/controller/base.rb', line 174

def action_name
  @meth
end

#controller_nameObject



170
171
172
# File 'lib/jets/controller/base.rb', line 170

def controller_name
  self.class.to_s.underscore
end

#controller_pathsObject



160
161
162
163
164
165
166
167
168
# File 'lib/jets/controller/base.rb', line 160

def controller_paths
  paths = []
  klass = self.class
  while klass != Jets::Controller::Base
    paths << klass.controller_path
    klass = klass.superclass
  end
  paths
end

#dispatch!Object

One key difference between process! vs dispatch!

process! - takes the request through the middleware stack
dispatch! - does not

dispatch! is useful for megamode or mounted applications



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/jets/controller/base.rb', line 77

def dispatch!
  method_override!

  t1 = Time.now
  log_start

  begin
    if run_before_actions(break_if: -> { @rendered })
      send(@meth)
      action_completed = true
    else
      Jets.logger.info "Filter chain halted as #{@last_callback_name} rendered or redirected"
    end

    triplet = ensure_render
    run_after_actions if action_completed
  rescue Exception => exception
    rescue_with_handler(exception) || raise
    triplet = ensure_render
  end

  took = Time.now - t1
  status = triplet[0]
  log_finish(status: status, took: took)
  triplet # status, headers, body
end

#event_logObject



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/jets/controller/base.rb', line 138

def event_log
  display_event = @event.dup

  if @event['isBase64Encoded']
    display_event['body'] = '[BASE64_ENCODED]'
  else
    display_event['body'] = parameter_filter.filter_json(display_event['body'])
  end

  display_event["queryStringParameters"] = parameter_filter.filter(display_event['queryStringParameters'])
  display_event["pathParameters"] = parameter_filter.filter(display_event['pathParameters'])
  json_dump(display_event)
end

#json_dump(data) ⇒ Object

Handles binary data safely



153
154
155
156
157
158
# File 'lib/jets/controller/base.rb', line 153

def json_dump(data)
  JSON.dump(data)
rescue Encoding::UndefinedConversionError
  data['body'] = '[BINARY]'
  JSON.dump(data)
end

#log_finish(options = {}) ⇒ Object

Documented interface method, careful not to rename



133
134
135
136
# File 'lib/jets/controller/base.rb', line 133

def log_finish(options={})
  status, took = options[:status], options[:took]
  Jets.logger.info "Completed Status Code #{status} in #{took}s"
end

#log_startObject

Documented interface method, careful not to rename



123
124
125
126
127
128
129
130
# File 'lib/jets/controller/base.rb', line 123

def log_start
  # JSON.dump makes logging look pretty in CloudWatch logs because it keeps it on 1 line
  ip = request.ip
  Jets.logger.info "Started #{@event['httpMethod']} \"#{@event['path']}\" for #{ip} at #{Time.now}"
  Jets.logger.info processing_log
  Jets.logger.info "  Event: #{event_log}"
  Jets.logger.info "  Parameters: #{JSON.dump(filtered_parameters.to_h)}"
end

#method_override!Object

Override @meth when POST with _method=delete By the time processing reaches dispatch which calls method_override! The Rack::MethodOverride middleware has overriden env with DELETE and set env



108
109
110
111
112
113
114
# File 'lib/jets/controller/base.rb', line 108

def method_override!
  env = request.env
  if env['rack.methodoverride.original_method'] && env['REQUEST_METHOD'] == 'DELETE'
    @original_meth = @meth
    @meth = "delete"
  end
end

#process!Object

One key difference between process! vs dispatch!

process! - takes the request through the middleware stack
dispatch! - does not

Most of the time, you want process! instead of dispatch!



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/jets/controller/base.rb', line 45

def process!
  adapter = Jets::Controller::Rack::Adapter.new(event, context)
  adapter.rack_vars(
    'jets.controller' => self,
    'lambda.context' => context,
    'lambda.event' => event,
    'lambda.meth' => meth,
  )

  # adapter.process calls
  #
  #     Jets.application.call(env)
  #
  # and that goes through the middleware stacks. The last middleware stack is Jets::Controller::Middleware::Main
  #
  #     class Jets::Controller::Middleware::Main
  #       def call!
  #         setup
  #         @controller.dispatch! # Returns triplet
  #       end
  #     end
  #
  adapter.process # Returns API Gateway hash structure
end

#processing_logObject



116
117
118
119
120
# File 'lib/jets/controller/base.rb', line 116

def processing_log
  processing = "Processing #{self.class.name}##{@meth}"
  processing << " (original method #{@original_meth})" if @original_meth
  processing
end