Module: Otto::Core::LifecycleHooks

Included in:
Otto
Defined in:
lib/otto/core/lifecycle_hooks.rb

Overview

Lifecycle hooks module for registering callbacks at various points in request processing. Provides the public API for request completion callbacks.

Instance Method Summary collapse

Instance Method Details

#handler_wrappersArray<Proc>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get registered handler wrapper factories (for internal use)

Returns:

  • (Array<Proc>)

    Array of registered wrapper factory blocks



138
139
140
# File 'lib/otto/core/lifecycle_hooks.rb', line 138

def handler_wrappers
  @handler_wrappers
end

#on_request_complete {|request, response, duration| ... } ⇒ self

Register a callback to be executed after each request completes

Instance-level request completion callbacks allow each Otto instance to have its own isolated set of callbacks, preventing duplicate invocations in multi-app architectures (e.g., Rack::URLMap).

The callback receives three arguments:

  • request: Rack::Request object

  • response: Rack::Response object (wrapping the response tuple)

  • duration: Request processing duration in microseconds

Examples:

Basic usage

otto = Otto.new(routes_file)
otto.on_request_complete do |req, res, duration|
  logger.info "Request completed", path: req.path, duration: duration
end

Multi-app architecture

# App 1: Core Web Application
core_router = Otto.new
core_router.on_request_complete do |req, res, duration|
  logger.info "Core app request", path: req.path
end

# App 2: API Application
api_router = Otto.new
api_router.on_request_complete do |req, res, duration|
  logger.info "API request", path: req.path
end

# Each callback only fires for its respective Otto instance

Yields:

  • (request, response, duration)

    Block to execute after each request

Yield Parameters:

  • request (Rack::Request)

    The request object

  • response (Rack::Response)

    The response object

  • duration (Integer)

    Duration in microseconds

Returns:

  • (self)

    Returns self for method chaining

Raises:

  • (FrozenError)

    if called after configuration is frozen



48
49
50
51
52
# File 'lib/otto/core/lifecycle_hooks.rb', line 48

def on_request_complete(&block)
  ensure_not_frozen!
  @request_complete_callbacks << block if block_given?
  self
end

#on_route_matched {|env, route_definition| ... } ⇒ self

Register a callback fired after a route matches but before the handler dispatches.

The callback receives two arguments:

  • env: the Rack environment hash

  • route_definition: the matched Otto::RouteDefinition

Unlike on_request_complete, exceptions raised inside on_route_matched callbacks are NOT swallowed: they propagate to Otto#handle_error so consumers can route custom error classes through register_error_handler.

Does not fire for static-file routes or for the 404 fallback route.

Examples:

otto.on_route_matched do |env, route_definition|
  raise MyApp::Maintenance if maintenance? && route_definition.auth_requirement
end

Yields:

  • (env, route_definition)

    Block to execute after route match

Yield Parameters:

  • env (Hash)

    The Rack environment

  • route_definition (Otto::RouteDefinition)

    The matched route definition

Returns:

  • (self)

    Returns self for method chaining

Raises:

  • (FrozenError)

    if called after configuration is frozen



84
85
86
87
88
# File 'lib/otto/core/lifecycle_hooks.rb', line 84

def on_route_matched(&block)
  ensure_not_frozen!
  @route_matched_callbacks << block if block_given?
  self
end

#register_handler_wrapper {|route_definition, inner_handler| ... } ⇒ self

Register a wrapper factory that composes around each route handler.

The block is invoked once per request, identical to RouteAuthWrapper instantiation, with the route’s definition and the inner (already wrapped) handler. It must return either the original inner_handler (to opt out for that route) or a new object responding to :call(env). Wrappers compose outermost-first in registration order:

request -> wrapper_1 -> wrapper_2 -> ... -> RouteAuthWrapper -> base_handler

RouteAuthWrapper always stays innermost so env is set before any consumer wrapper sees the request.

Factory blocks are exercised once against every loaded route during freeze_configuration! (see validate_handler_wrappers!) so factories that raise unconditionally or return non-callables surface at boot rather than on the first request that happens to match.

Examples:

Gate a route by an option set in the routes file

otto.register_handler_wrapper do |route_definition, inner_handler|
  next inner_handler unless route_definition.option(:scope) == 'canonical'
  MyApp::CanonicalOnlyWrapper.new(inner_handler, route_definition)
end

Yields:

  • (route_definition, inner_handler)

    Factory invoked per request

Yield Parameters:

  • route_definition (Otto::RouteDefinition)

    The route being wrapped

  • inner_handler (#call)

    The handler to wrap (RouteAuthWrapper or base)

Yield Returns:

  • (#call)

    A callable wrapper, or inner_handler unchanged to skip

Returns:

  • (self)

    Returns self for method chaining

Raises:

  • (FrozenError)

    if called after configuration is frozen



128
129
130
131
132
# File 'lib/otto/core/lifecycle_hooks.rb', line 128

def register_handler_wrapper(&block)
  ensure_not_frozen!
  @handler_wrappers << block if block_given?
  self
end

#request_complete_callbacksArray<Proc>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get registered request completion callbacks (for internal use)

Returns:

  • (Array<Proc>)

    Array of registered callback blocks



58
59
60
# File 'lib/otto/core/lifecycle_hooks.rb', line 58

def request_complete_callbacks
  @request_complete_callbacks
end

#route_matched_callbacksArray<Proc>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get registered route matched callbacks (for internal use)

Returns:

  • (Array<Proc>)

    Array of registered callback blocks



94
95
96
# File 'lib/otto/core/lifecycle_hooks.rb', line 94

def route_matched_callbacks
  @route_matched_callbacks
end