Class: Wurk::API::Router

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

Overview

Path table for the HTTP API. Deliberately not ActionDispatch: the API has to route in standalone mode, where Rails is never loaded (CLAUDE.md — "standalone mode must run without loading the engine").

Patterns are literal segments plus :name captures ('/jobs/:jid'). A capture never spans '/', so a queue named "a/b" has to arrive percent-encoded — the same constraint config/routes.rb puts on the dashboard's :name.

Every route names the Auth scope its caller must hold. The router only records it — App#dispatch enforces it — but the keyword is required, so adding an endpoint without deciding who may call it is impossible rather than merely discouraged. A new route can never default open.

Defined Under Namespace

Classes: Match, Route

Constant Summary collapse

NO_PARAMS =
{}.freeze

Instance Method Summary collapse

Constructor Details

#initializeRouter

Returns a new instance of Router.



30
31
32
# File 'lib/wurk/api/router.rb', line 30

def initialize
  @routes = []
end

Instance Method Details

#delete(pattern, scope:, &handler) ⇒ Object



36
# File 'lib/wurk/api/router.rb', line 36

def delete(pattern, scope:, &handler) = add('DELETE', pattern, scope, handler)

#get(pattern, scope:, &handler) ⇒ Object



34
# File 'lib/wurk/api/router.rb', line 34

def get(pattern, scope:, &handler) = add('GET', pattern, scope, handler)

#match(verb, path) ⇒ Object

HEAD is served by the GET route (RFC 9110 §9.3.2); the caller drops the body.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/wurk/api/router.rb', line 40

def match(verb, path)
  verb = 'GET' if verb == 'HEAD'
  segments = split(path).map { |seg| ::Rack::Utils.unescape_path(seg) }
  allowed = []
  @routes.each do |route|
    params = bind(route.segments, segments)
    next unless params
    if route.verb == verb
      return Match.new(handler: route.handler, params: params, scope: route.scope, allowed: nil)
    end

    allowed << route.verb
  end
  Match.new(handler: nil, params: NO_PARAMS, scope: nil, allowed: allowed.uniq)
end

#post(pattern, scope:, &handler) ⇒ Object



35
# File 'lib/wurk/api/router.rb', line 35

def post(pattern, scope:, &handler) = add('POST', pattern, scope, handler)