Class: Otto::Route

Inherits:
Object
  • Object
show all
Defined in:
lib/otto/route.rb

Overview

Otto::Route

A Route is a definition of a URL path and the method to call when that path is requested. Each route represents a single line in a routes file.

Routes include built-in security features:

  • Class name validation to prevent code injection

  • Automatic security header injection

  • CSRF protection when enabled

  • Input validation and sanitization

e.g.

GET   /uri/path      YourApp.method
GET   /uri/path2     YourApp#method

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(verb, path, definition) ⇒ Route

Initialize a new route with security validations

Parameters:

  • verb (String)

    HTTP verb (GET, POST, PUT, DELETE, etc.)

  • path (String)

    URL path pattern with optional parameters

  • definition (String)

    Class and method definition (Class.method or Class#method)

Raises:

  • (ArgumentError)

    if definition format is invalid or class name is unsafe



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/otto/route.rb', line 35

def initialize(verb, path, definition)
  @verb = verb.to_s.upcase.to_sym
  @path = path
  @definition = definition
  @pattern, @keys = *compile(@path)
  if !@definition.index('.').nil?
    @klass, @name = @definition.split('.')
    @kind = :class
  elsif !@definition.index('#').nil?
    @klass, @name = @definition.split('#')
    @kind = :instance
  else
    raise ArgumentError, "Bad definition: #{@definition}"
  end
  @klass = safe_const_get(@klass)
  # @method = @klass.method(@name)
end

Instance Attribute Details

#definitionObject (readonly)

Returns the value of attribute definition.



26
27
28
# File 'lib/otto/route.rb', line 26

def definition
  @definition
end

#keysObject (readonly)

Returns the value of attribute keys.



26
27
28
# File 'lib/otto/route.rb', line 26

def keys
  @keys
end

#kindObject (readonly)

Returns the value of attribute kind.



26
27
28
# File 'lib/otto/route.rb', line 26

def kind
  @kind
end

#klassObject (readonly)

Returns the value of attribute klass.



26
27
28
# File 'lib/otto/route.rb', line 26

def klass
  @klass
end

#methodObject (readonly)

Returns the value of attribute method.



26
27
28
# File 'lib/otto/route.rb', line 26

def method
  @method
end

#nameObject (readonly)

Returns the value of attribute name.



26
27
28
# File 'lib/otto/route.rb', line 26

def name
  @name
end

#ottoObject

Returns the value of attribute otto.



27
28
29
# File 'lib/otto/route.rb', line 27

def otto
  @otto
end

#pathObject (readonly)

Returns the value of attribute path.



26
27
28
# File 'lib/otto/route.rb', line 26

def path
  @path
end

#patternObject (readonly)

Returns the value of attribute pattern.



26
27
28
# File 'lib/otto/route.rb', line 26

def pattern
  @pattern
end

#verbObject (readonly)

Returns the value of attribute verb.



26
27
28
# File 'lib/otto/route.rb', line 26

def verb
  @verb
end

Instance Method Details

#call(env, extra_params = {}) ⇒ Array

Execute the route by calling the associated class method

This method handles the complete request/response cycle with built-in security:

  • Processes parameters through the security layer

  • Adds configured security headers to the response

  • Extends request/response with security helpers when enabled

  • Provides CSRF and validation helpers to the target class

Parameters:

  • env (Hash)

    Rack environment hash

  • extra_params (Hash) (defaults to: {})

    Additional parameters to merge (default: {})

Returns:

  • (Array)

    Rack response array [status, headers, body]



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/otto/route.rb', line 110

def call(env, extra_params = {})
  extra_params ||= {}
  req = Rack::Request.new(env)
  res = Rack::Response.new
  req.extend Otto::RequestHelpers
  res.extend Otto::ResponseHelpers
  res.request = req

  # Process parameters through security layer
  req.params.merge! extra_params
  req.params.replace Otto::Static.indifferent_params(req.params)

  # Add security headers
  if otto.respond_to?(:security_config) && otto.security_config
    otto.security_config.security_headers.each do |header, value|
      res.headers[header] = value
    end
  end

  klass.extend Otto::Route::ClassMethods
  klass.otto = otto

  # Add security helpers if CSRF is enabled
  if otto.respond_to?(:security_config) && otto.security_config&.csrf_enabled?
    res.extend Otto::Security::CSRFHelpers
  end

  # Add validation helpers
  res.extend Otto::Security::ValidationHelpers

  case kind
  when :instance
    inst = klass.new req, res
    inst.send(name)
  when :class
    klass.send(name, req, res)
  else
    raise "Unsupported kind for #{@definition}: #{kind}"
  end
  res.body = [res.body] unless res.body.respond_to?(:each)
  res.finish
end

#pattern_regexpObject



95
96
97
# File 'lib/otto/route.rb', line 95

def pattern_regexp
  Regexp.new(@path.gsub('/*', '/.+'))
end