Class: Rubino::API::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/api/router.rb

Overview

Minimal pattern-matching router mapping HTTP verb + path to an Operation class.

Path patterns support ‘:name` captures (e.g. “/v1/sessions/:id”), compiled to a `[^/]+` regex group. On a match the captures become Request#params, the original pattern is stashed on env (low-cardinality label for Observability), and the operation’s return value is coerced via Responses.

Operation contract: ‘.call(request)` returning one of:

- Hash                                  → 200 JSON
- [status, body_hash]                   → status + JSON body
- [status, headers, body_iterable]      → raw Rack triple
- object responding to #to_rack         → delegated

router = Router.new
router.get  "/v1/health",        to: HealthOperation
router.post "/v1/sessions",      to: Sessions::CreateOperation
router.get  "/v1/sessions/:id",  to: Sessions::ShowOperation

Defined Under Namespace

Classes: Route

Constant Summary collapse

HTTP_METHODS =
%i[get post put patch delete].freeze

Instance Method Summary collapse

Constructor Details

#initializeRouter

Returns a new instance of Router.



27
28
29
# File 'lib/rubino/api/router.rb', line 27

def initialize
  @routes = []
end

Instance Method Details

#call(env) ⇒ Array(Integer, Hash, Array<String>)

Rack entry point. Matches in registration order; first match wins. Returns a 404 JSON response when nothing matches.

Returns:

  • (Array(Integer, Hash, Array<String>))

    Rack response triple



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rubino/api/router.rb', line 41

def call(env)
  rack_method = env["REQUEST_METHOD"]
  path = env["PATH_INFO"]

  @routes.each do |route|
    next unless route.method == rack_method

    match = route.pattern.match(path)
    next unless match

    params = route.keys.zip(match.captures).to_h
    env["rubino.route"] = route.original_path
    request = Request.new(env, params)
    return Responses.coerce(route.operation.call(request))
  end

  Responses.json(404, error: { code: "not_found", message: "route not found: #{rack_method} #{path}" })
end