sinatra-router 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/lib/sinatra/router.rb +91 -0
  2. metadata +47 -0
@@ -0,0 +1,91 @@
1
+ module Sinatra
2
+ class Router
3
+ def initialize(app=nil, *args, &block)
4
+ @app = app
5
+ @apps = []
6
+ @conditions = []
7
+
8
+ instance_eval(&block) if block
9
+ @routes = build_routing_table
10
+ end
11
+
12
+ def call(env)
13
+ if ret = try_route(env["REQUEST_METHOD"], env["PATH_INFO"], env)
14
+ ret
15
+ else
16
+ raise "neither @app nor @run is set" if !@app && !@run
17
+
18
+ # if set as middlware, prefer that, otherwise try default run module
19
+ (@app || @run).call(env)
20
+ end
21
+ end
22
+
23
+ # specify the default app to run if no other app routes matched
24
+ def run(app)
25
+ raise "@run already set" if @run
26
+ @run = app
27
+ end
28
+
29
+ def route(app, *conditions)
30
+ # mix in context based conditions with conditions given by parameter
31
+ @apps << [app, @conditions + conditions]
32
+ end
33
+
34
+ # yield to a builder block in which all defined apps will only respond for
35
+ # the given version
36
+ def version(version, &block)
37
+ @conditions = { version: version }
38
+ instance_eval(&block) if block
39
+ @conditions = {}
40
+ end
41
+
42
+ protected
43
+
44
+ def with_conditions(*args, &block)
45
+ old = @conditions
46
+ @conditions = @conditions + args
47
+ instance_eval(&block) if block
48
+ @conditions = old
49
+ end
50
+
51
+ private
52
+
53
+ def build_routing_table
54
+ all_routes = {}
55
+ @apps.each do |app, conditions|
56
+ next unless app.respond_to?(:routes)
57
+ app.routes.each do |verb, routes|
58
+ all_routes[verb] ||= []
59
+ all_routes[verb] += routes.map do |pattern, _, _, _|
60
+ [pattern, conditions, app]
61
+ end
62
+ end
63
+ end
64
+ all_routes
65
+ end
66
+
67
+ def conditions_match?(conditions, env)
68
+ conditions.each do |condition|
69
+ return false unless condition.call(env)
70
+ end
71
+ true
72
+ end
73
+
74
+ def try_route(verb, path, env)
75
+ # see Sinatra's `route!`
76
+ if verb_routes = @routes[verb]
77
+ verb_routes.each do |pattern, conditions, app|
78
+ if match = pattern.match(path) && conditions_match?(conditions, env)
79
+ status, headers, response = app.call(env)
80
+
81
+ # if we got a pass, keep trying routes
82
+ return nil if headers["X-Cascade"] == "pass"
83
+
84
+ return status, headers, response
85
+ end
86
+ end
87
+ end
88
+ nil
89
+ end
90
+ end
91
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-router
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brandur
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-24 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description:
15
+ email: brandur@mutelight.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/sinatra/router.rb
21
+ homepage: https://github.com/brandur/sinatra-router
22
+ licenses:
23
+ - MIT
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 1.8.24
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: A tiny vendorable router that makes it easy to try routes from a number of
46
+ different modular Sinatra applications.
47
+ test_files: []