sinatra-router 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []