Class: Takagi::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/takagi/router.rb,
lib/takagi/router/route_matcher.rb,
lib/takagi/router/metadata_extractor.rb

Direct Known Subclasses

Base

Defined Under Namespace

Classes: MetadataExtractor, RouteContext, RouteEntry, RouteMatcher

Constant Summary collapse

DEFAULT_CONTENT_FORMAT =
Takagi::CoAP::Registries::ContentFormat::JSON

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRouter

Returns a new instance of Router.



144
145
146
147
148
149
150
# File 'lib/takagi/router.rb', line 144

def initialize
  @routes = {}
  @routes_mutex = Mutex.new # Protects route modifications in multithreaded environments
  @logger = Takagi.logger
  @route_matcher = RouteMatcher.new(@logger)
  @metadata_extractor = MetadataExtractor.new(@logger)
end

Class Method Details

.instanceRouter

Global singleton instance for backward compatibility with Takagi::Base New code should create Router instances directly

Returns:

  • (Router)

    The global router instance



19
20
21
# File 'lib/takagi/router.rb', line 19

def instance
  @instance ||= new
end

.reset!void

This method returns an undefined value.

Reset the global instance (primarily for testing)



26
27
28
29
30
# File 'lib/takagi/router.rb', line 26

def reset!
  @instance = nil
  # Ensure Takagi::Base fetches a fresh router after reset
  Takagi::Base.instance_variable_set(:@router, nil) if defined?(Takagi::Base)
end

Instance Method Details

#add_route(method, path, metadata: {}, &block) ⇒ Object

Registers a new route for a given HTTP method and path

Parameters:

  • method (String)

    The HTTP method (GET, POST, etc.)

  • path (String)

    The URL path, can include dynamic segments like ‘:id`

  • block (Proc)

    The handler to be executed when the route is matched



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/takagi/router.rb', line 156

def add_route(method, path, metadata: {}, &block)
  @routes_mutex.synchronize do
    entry = build_route_entry(method, path, , block)
    @routes["#{method} #{path}"] = entry
    @logger.debug "Add new route: #{method} #{path}"

    # Extract metadata from core blocks inside the handler
    (entry) if block

    Takagi::Hooks.emit(
      :router_route_added,
      method: method,
      path: path,
      entry: entry
    )
  end
end

#all_routesObject



193
194
195
# File 'lib/takagi/router.rb', line 193

def all_routes
  @routes.values.map { |entry| "#{entry.method} #{entry.path}" }
end

#configure_core(method, path, &block) ⇒ Object

Applies CoRE metadata outside the request cycle. Useful for boot time configuration where the DSL block does not have a live request object.



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/takagi/router.rb', line 231

def configure_core(method, path, &block)
  return unless block

  @routes_mutex.synchronize do
    entry = @routes["#{method} #{path}"]
    unless entry
      @logger.warn "configure_core skipped: #{method} #{path} not registered"
      return
    end

    entry.configure_attributes(&block)
  end
end

#find_observable(path) ⇒ Object



197
198
199
# File 'lib/takagi/router.rb', line 197

def find_observable(path)
  @routes.values.find { |entry| entry.method == 'OBSERVE' && entry.path == path }
end

#find_route(method, path) ⇒ Proc, Hash

Finds a registered route for a given method and path

Parameters:

  • method (String)

    HTTP method

  • path (String)

    URL path

Returns:

  • (Proc, Hash)

    The matching handler and extracted parameters



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/takagi/router.rb', line 205

def find_route(method, path)
  @routes_mutex.synchronize do
    @logger.debug "Routes: #{@routes.inspect}"
    @logger.debug "Looking for route: #{method} #{path}"
    entry = @routes["#{method} #{path}"]
    params = {}

    return wrap_block(entry), params if entry

    @logger.debug '[Debug] Find dynamic route'
    entry, params = match_dynamic_route(method, path)

    return wrap_block(entry), params if entry

    [nil, {}]
  end
end


223
224
225
226
227
# File 'lib/takagi/router.rb', line 223

def link_format_entries
  @routes_mutex.synchronize do
    @routes.values.reject { |entry| entry.[:discovery] }.map(&:dup)
  end
end

#observable(path, metadata: {}, &block) ⇒ Object

Registers a OBSERVE route

Parameters:

  • path (String)

    The URL path

  • block (Proc)

    The handler function



188
189
190
191
# File 'lib/takagi/router.rb', line 188

def observable(path, metadata: {}, &block)
   = { obs: true, rt: 'core#observable', if: 'takagi.observe' }
  add_route('OBSERVE', path, metadata: .merge(), &block)
end