Class: Mustermann::Router

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

Overview

An extremely simple, Rack-compatible router implementation using Set for pattern matching.

Examples:

Basic usage

require 'mustermann/router'

router = Mustermann::Router.new do
  get "/hello/:name" do |env|
    name = env["mustermann.match"][:name]
    [200, { "content-type" => "text/plain" }, ["Hello, #{name}!"]]
  end
end

# in config.ru
use Rack::Head
run router

Routing to other applications

router = Mustermann::Router.new do
  get  "/users",     MyApp::Users::Index
  get  "/users/:id", MyApp::Users::Show
  post "/users",     MyApp::Users::Create
  fallback           MyApp::NotFound
end

router.path_for(MyApp::Users::Show, id: 42) # => "/users/42"

As middleware

use Mustermann::Router do
  get("/up") { [200, { "content-type" => "text/plain" }, ["Up!"]] }
end

run MyApp

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(fallback = nil, key: "mustermann.match", **options, &block) ⇒ Router

Initializes a new router.

Parameters:

  • key (String) (defaults to: "mustermann.match")

    The key under which the route match will be stored in the Rack environment hash (default: “mustermann.match”).

  • options (Hash)

    Options to be passed to the Mustermann patterns.



49
50
51
52
53
54
55
56
57
58
# File 'lib/mustermann/router.rb', line 49

def initialize(fallback = nil, key: "mustermann.match", **options, &block)
  @key      = key
  @sets     = VERBS.to_h { |verb| [verb, Set.new(**options)] }
  @fallback = fallback || ->(env) { NOT_FOUND.dup }

  if block_given?
    instance_exec(&block)
    @sets.each_value(&:optimize!)
  end
end

Instance Method Details

#call(env) ⇒ Array

Returns The Rack response array (status, headers, body).

Parameters:

  • env (Hash)

    The Rack environment hash for the request.

Returns:

  • (Array)

    The Rack response array (status, headers, body).



62
63
64
65
66
67
68
69
70
# File 'lib/mustermann/router.rb', line 62

def call(env)
  request_method = env["REQUEST_METHOD"] || "GET"
  request_method = "GET" if request_method == "HEAD"
  if routes = @sets[request_method] and match = routes.match(env["PATH_INFO"] || "/")
    env[@key] = match
    return match.value.call(env)
  end
  @fallback.call(env)
end

#fallback(fallback = nil, &block) ⇒ Object



72
# File 'lib/mustermann/router.rb', line 72

def fallback(fallback = nil, &block) = @fallback = fallback || block || @fallback

#path_for(app, behavior = nil, params = {}) ⇒ String

Helps generate links

Parameters:

  • app (#call)

    The Rack application or middleware for which to generate the path.

  • behavior (Symbol) (defaults to: nil)

    What to do with additional key/value pairs not present in the values hash. Possible options: :raise, :ignore, :append.

  • values (Hash{Symbol: #to_s, Array<#to_s>})

    Values to use for expansion.

Returns:

  • (String)

    The generated path.



95
96
97
98
# File 'lib/mustermann/router.rb', line 95

def path_for(app, behavior = nil, params = {})
  set = @sets.values.find { |s| s.has_value?(app) } || @sets[VERBS.first]
  set.expand(app, behavior, params)
end

#route(verb, pattern, target = nil, **options) {|env| ... } ⇒ void

Note:

Shorthand methods, like ‘get`, `post`, etc. dynamically are defined for all supported verbs.

This method returns an undefined value.

Adds a route for the given verb and pattern, with the given target.

Parameters:

  • verb (String)

    HTTP verb (e.g. “GET”, “POST”)

  • pattern (String, Mustermann::Pattern)

    Pattern string or Mustermann pattern (e.g. “/users/:id”)

  • target (#call, nil) (defaults to: nil)

    The Rack application or middleware to call when the route matches. Can be passed a block as well.

Yields:

  • (env)

    Block to be used as the target if no explicit target is given.

Yield Parameters:

  • env (Hash)

    The Rack environment hash for the request.

Raises:

  • (ArgumentError)


84
85
86
87
88
# File 'lib/mustermann/router.rb', line 84

def route(verb, pattern, target = nil, **options, &block)
  raise ArgumentError, "need to provide target, :to or a block" unless target || block
  raise ArgumentError, "unknown verb: #{verb}" unless VERBS.include?(verb)
  @sets[verb].add(pattern, target || block)
end