http_router 0.3.10 → 0.3.11

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.
@@ -14,7 +14,7 @@ This is very new code. Lots of stuff probably doesn't work right. I will likely
14
14
  * Regex support for variables.
15
15
  * Request condition support.
16
16
  * Partial matches.
17
- * Supports interstitial variables (e.g. /my-:variable-brings.all.the.boys/yard).
17
+ * Supports interstitial variables (e.g. /my-:variable-brings.all.the.boys/yard) and unnamed variable /one/:/two
18
18
  * Very fast and small code base (~1,000 loc).
19
19
  * Sinatra compatibility.
20
20
 
data/Rakefile CHANGED
@@ -1,18 +1,15 @@
1
1
  require 'rubygems'
2
+ require 'bundler'
2
3
  require 'spec'
4
+ require 'code_stats'
3
5
  require 'spec/rake/spectask'
6
+
4
7
  Spec::Rake::SpecTask.new(:spec) do |t|
5
8
  t.spec_opts ||= []
6
9
  t.spec_opts << "--options" << "spec/spec.opts"
7
10
  t.spec_files = FileList['spec/**/*_spec.rb']
8
11
  end
9
12
 
10
- begin
11
- require 'code_stats'
12
- CodeStats::Tasks.new
13
- rescue LoadError
14
- end
15
-
16
13
  require 'rake/rdoctask'
17
14
  desc "Generate documentation"
18
15
  Rake::RDocTask.new do |rd|
@@ -21,6 +18,5 @@ Rake::RDocTask.new do |rd|
21
18
  rd.rdoc_dir = 'rdoc'
22
19
  end
23
20
 
24
- require 'ext/gem_rake'
25
-
26
- Bundler::GemHelper.install_tasks
21
+ Bundler::GemHelper.install_tasks
22
+ CodeStats::Tasks.new(:reporting_depth => 3)
@@ -1,5 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'rbench'
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+
3
6
  require 'lib/http_router'
4
7
 
5
8
  u = HttpRouter.new
@@ -23,10 +23,11 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency 'rack', '>=1.0'
24
24
  s.add_runtime_dependency 'url_mount', '>=0.2.1'
25
25
  s.add_development_dependency 'rspec'
26
+ s.add_development_dependency 'code_stats'
26
27
  s.add_development_dependency 'rake'
27
28
  s.add_development_dependency 'sinatra'
28
29
  s.add_development_dependency 'rbench'
29
- s.add_development_dependency 'tumbler', ">= 0.0.11"
30
+ s.add_development_dependency 'bundler', ">= 1.0.0.rc4"
30
31
 
31
32
  if s.respond_to? :specification_version then
32
33
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -1,5 +1,3 @@
1
- $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
2
-
3
1
  require 'rack'
4
2
  require 'url_mount'
5
3
  require 'ext/rack/uri_escape'
@@ -133,10 +133,10 @@ class HttpRouter
133
133
  current_nodes
134
134
  end
135
135
 
136
- def find_on_parts(request, parts, params, alternate_request_methods)
136
+ def find_on_parts(request, parts, params)
137
137
  if parts and !parts.empty?
138
138
  if parts.size == 1 and parts.first == ''
139
- potential_match = find_on_parts(request, [], params, alternate_request_methods)
139
+ potential_match = find_on_parts(request, [], params)
140
140
  if potential_match and (router.ignore_trailing_slash? or potential_match.value && potential_match.value.route.trailing_slash_ignore?)
141
141
  parts.shift
142
142
  return potential_match
@@ -149,10 +149,10 @@ class HttpRouter
149
149
  if tester.respond_to?(:matches?) and match = tester.matches?(parts)
150
150
  dupped_parts = parts.dup
151
151
  params.push((val = tester.consume(match, dupped_parts) and val.is_a?(Array)) ? val.map{|v| Rack::Utils.uri_unescape(v)} : Rack::Utils.uri_unescape(val))
152
- parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params, alternate_request_methods)
152
+ parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
153
153
  elsif tester.respond_to?(:match) and match = tester.match(parts.whole_path) and match.begin(0) == 0
154
154
  dupped_parts = router.split(parts.whole_path[match[0].size, parts.whole_path.size])
155
- parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params, alternate_request_methods)
155
+ parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
156
156
  else
157
157
  nil
158
158
  end
@@ -161,14 +161,14 @@ class HttpRouter
161
161
  end
162
162
  if match = @lookup && @lookup[parts.first]
163
163
  parts.shift
164
- return match.find_on_parts(request, parts, params, alternate_request_methods)
164
+ return match.find_on_parts(request, parts, params)
165
165
  elsif @catchall
166
166
  params.push((val = @catchall.variable.consume(nil, parts) and val.is_a?(Array)) ? val.map{|v| Rack::Utils.uri_unescape(v)} : Rack::Utils.uri_unescape(val))
167
- return @catchall.find_on_parts(request, parts, params, alternate_request_methods)
167
+ return @catchall.find_on_parts(request, parts, params)
168
168
  end
169
169
  end
170
170
  if request_node
171
- request_node.find_on_request_methods(request, alternate_request_methods)
171
+ request_node.find_on_request_methods(request)
172
172
  elsif arbitrary_node
173
173
  arbitrary_node.find_on_arbitrary(request)
174
174
  elsif @value
@@ -203,7 +203,7 @@ class HttpRouter
203
203
  RequestMethods = [:request_method, :host, :port, :scheme, :user_agent, :ip, :fullpath, :query_string]
204
204
  attr_accessor :request_method
205
205
 
206
- def find_on_request_methods(request, alternate_request_methods)
206
+ def find_on_request_methods(request)
207
207
  if @request_method
208
208
  request_method_satisfied = false
209
209
  request_value = request.send(request_method)
@@ -212,23 +212,19 @@ class HttpRouter
212
212
  regexp === request_value
213
213
  end
214
214
  request_method_satisfied = true if next_node
215
- next_node &&= next_node.last.find_on_request_methods(request, alternate_request_methods)
215
+ next_node &&= next_node.last.find_on_request_methods(request)
216
216
  return next_node if next_node
217
217
  end
218
218
  if @lookup and next_node = @lookup[request_value]
219
219
  request_method_satisfied = true
220
- next_node = next_node.find_on_request_methods(request, alternate_request_methods)
220
+ next_node = next_node.find_on_request_methods(request)
221
221
  return next_node if next_node
222
222
  end
223
223
  if @catchall
224
224
  request_method_satisfied = true
225
- next_node = @catchall.find_on_request_methods(request, alternate_request_methods)
225
+ next_node = @catchall.find_on_request_methods(request)
226
226
  return next_node if next_node
227
227
  end
228
- if @request_method == :request_method
229
- alternate_request_methods.concat(@lookup.keys)
230
- alternate_request_methods.request_method_found ||= request_method_satisfied
231
- end
232
228
  end
233
229
 
234
230
  if @arbitrary_node
@@ -1,5 +1,7 @@
1
1
  class HttpRouter
2
2
  class Root < Node
3
+ HttpRequestMethods = %w(HEAD GET HEAD POST DELETE PUT)
4
+
3
5
  class AlternativeRequestMethods < Array
4
6
  attr_accessor :request_method_found
5
7
  end
@@ -10,26 +12,21 @@ class HttpRouter
10
12
  end
11
13
 
12
14
  def find(request)
13
- path = request.path_info.dup
14
- parts = router.split(path)
15
- parts << '' if path[path.size - 1] == ?/
16
15
  params = []
17
- alternate_request_methods = AlternativeRequestMethods.new
18
- alternate_request_methods.request_method_found = false
19
- process_response(
20
- find_on_parts(request, parts, params, alternate_request_methods),
21
- parts,
22
- params,
23
- request,
24
- alternate_request_methods
25
- )
16
+ parts = get_parts(request)
17
+ node = find_on_parts(request, parts, params)
18
+ process_response(node, parts, params, request)
26
19
  end
27
-
20
+
21
+ def get_parts(request)
22
+ parts = router.split(request.path_info.dup)
23
+ parts << '' if request.path_info[-1] == ?/
24
+ parts
25
+ end
26
+
28
27
  private
29
- def process_response(node, parts, params, request, alternate_request_methods)
30
- if node.respond_to?(:matched?) && !node.matched?
31
- node
32
- elsif node && node.value
28
+ def process_response(node, parts, params, request)
29
+ if node && node.value
33
30
  if parts.empty?
34
31
  Response.matched(node.value, params, request.path_info)
35
32
  elsif node.value.route.partially_match?
@@ -39,10 +36,17 @@ class HttpRouter
39
36
  nil
40
37
  end
41
38
  else
42
- if alternate_request_methods.request_method_found or alternate_request_methods.empty?
39
+ alternate_methods = (HttpRequestMethods - [request.request_method]).select do |alternate_method|
40
+ test_request = request.dup
41
+ test_request.env['REQUEST_METHOD'] = alternate_method
42
+ node = find_on_parts(test_request, get_parts(request), [])
43
+ node && node.value
44
+ end
45
+
46
+ if alternate_methods.empty?
43
47
  nil
44
48
  else
45
- Response.unmatched(405, {"Allow" => alternate_request_methods.uniq.join(", ")})
49
+ Response.unmatched(405, {"Allow" => alternate_methods.join(", ")})
46
50
  end
47
51
  end
48
52
  end
@@ -301,23 +301,23 @@ class HttpRouter
301
301
  paths = HttpRouter::OptionalCompiler.new(@path).paths
302
302
  paths.map do |path|
303
303
  splitting_indexes = []
304
- variable_counter = 0
304
+ variable_position = 0
305
305
  counter = 0
306
306
  original_path = path.dup
307
307
  split_path = router.split(path)
308
- index = 0
308
+ position = 0
309
309
  new_path = split_path.map do |part|
310
- r = case part
310
+ processed_parts = case part
311
311
  when /^:([a-zA-Z_0-9]*)$/
312
312
  v_name = ($1.empty? ? anonymous_variable(counter += 1) : $1).to_sym
313
313
  router.variable(v_name, @matches_with[v_name])
314
314
  when /^\*([a-zA-Z_0-9]*)$/
315
- if index != split_path.size - 1
315
+ if position != split_path.size - 1
316
316
  v_name = ($1.empty? ? anonymous_variable(counter += 1) : $1).to_sym
317
- splitting_indexes << variable_counter
318
- remaining_path_parts = split_path[index + 1, split_path.size]
317
+ splitting_indexes << variable_position
318
+ remaining_path_parts = split_path[position + 1, split_path.size]
319
319
  look_ahead_variable = remaining_path_parts.find{|p| p[0] == ?: || p[0] == ?*}
320
- remaining_matcher = split_path[index + 1, look_ahead_variable ? remaining_path_parts.index(look_ahead_variable) : split_path.size].join('/')
320
+ remaining_matcher = split_path[position + 1, look_ahead_variable ? remaining_path_parts.index(look_ahead_variable) : split_path.size].join('/')
321
321
  remaining_path_parts.index(look_ahead_variable) if look_ahead_variable
322
322
  router.variable(v_name, /^(#{@matches_with[v_name] || '[^\/]*?'}\/)+(?=#{Regexp.quote(remaining_matcher)})/)
323
323
  else
@@ -327,9 +327,9 @@ class HttpRouter
327
327
  else
328
328
  generate_interstitial_parts(part)
329
329
  end
330
- variable_counter += Array(r).select{|part| part.is_a?(Variable)}.size
331
- index += 1
332
- r
330
+ variable_position += Array(processed_parts).select{|part| part.is_a?(Variable)}.size
331
+ position += 1
332
+ processed_parts
333
333
  end
334
334
  new_path.flatten!
335
335
  Path.new(self, original_path, new_path, splitting_indexes.empty? ? nil : splitting_indexes)
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  class HttpRouter #:nodoc
3
- VERSION = '0.3.10'
3
+ VERSION = '0.3.11'
4
4
  end
@@ -9,7 +9,7 @@ describe "HttpRouter" do
9
9
  route = @router.add('/:test', :conditions => {:request_method => %w{HEAD GET}, :host => 'host1'}, :default_values => {:page => 1}, :matching => {:test => /\d+/}, :name => :foobar).to :test
10
10
  @router.recognize(Rack::MockRequest.env_for('http://host2/variable', :method => 'POST')).should be_nil
11
11
  @router.recognize(Rack::MockRequest.env_for('http://host1/variable', :method => 'POST')).should be_nil
12
- @router.recognize(Rack::MockRequest.env_for('http://host2/123', :method => 'POST')).matched?.should be_false
12
+ @router.recognize(Rack::MockRequest.env_for('http://host2/123', :method => 'POST')).should be_nil
13
13
  @router.recognize(Rack::MockRequest.env_for('http://host1/123', :method => 'POST')).matched?.should be_false
14
14
  @router.recognize(Rack::MockRequest.env_for('http://host1/123', :method => 'GET' )).route.dest.should == :test
15
15
  @router.url(:foobar, '123').should == '/123?page=1'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http_router
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 10
10
- version: 0.3.10
9
+ - 11
10
+ version: 0.3.11
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joshua Hull
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-06 00:00:00 -07:00
18
+ date: 2010-08-08 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -64,7 +64,7 @@ dependencies:
64
64
  type: :development
65
65
  version_requirements: *id003
66
66
  - !ruby/object:Gem::Dependency
67
- name: rake
67
+ name: code_stats
68
68
  prerelease: false
69
69
  requirement: &id004 !ruby/object:Gem::Requirement
70
70
  none: false
@@ -78,7 +78,7 @@ dependencies:
78
78
  type: :development
79
79
  version_requirements: *id004
80
80
  - !ruby/object:Gem::Dependency
81
- name: sinatra
81
+ name: rake
82
82
  prerelease: false
83
83
  requirement: &id005 !ruby/object:Gem::Requirement
84
84
  none: false
@@ -92,7 +92,7 @@ dependencies:
92
92
  type: :development
93
93
  version_requirements: *id005
94
94
  - !ruby/object:Gem::Dependency
95
- name: rbench
95
+ name: sinatra
96
96
  prerelease: false
97
97
  requirement: &id006 !ruby/object:Gem::Requirement
98
98
  none: false
@@ -106,21 +106,36 @@ dependencies:
106
106
  type: :development
107
107
  version_requirements: *id006
108
108
  - !ruby/object:Gem::Dependency
109
- name: tumbler
109
+ name: rbench
110
110
  prerelease: false
111
111
  requirement: &id007 !ruby/object:Gem::Requirement
112
112
  none: false
113
113
  requirements:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
- hash: 9
116
+ hash: 3
117
117
  segments:
118
118
  - 0
119
- - 0
120
- - 11
121
- version: 0.0.11
119
+ version: "0"
122
120
  type: :development
123
121
  version_requirements: *id007
122
+ - !ruby/object:Gem::Dependency
123
+ name: bundler
124
+ prerelease: false
125
+ requirement: &id008 !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 977940573
131
+ segments:
132
+ - 1
133
+ - 0
134
+ - 0
135
+ - rc4
136
+ version: 1.0.0.rc4
137
+ type: :development
138
+ version_requirements: *id008
124
139
  description: This library allows you to recognize and build URLs in a Rack application. As well it contains an interface for use within Sinatra.
125
140
  email: joshbuddy@gmail.com
126
141
  executables: []
@@ -135,7 +150,6 @@ files:
135
150
  - Gemfile
136
151
  - README.rdoc
137
152
  - Rakefile
138
- - Tumbler
139
153
  - benchmarks/gen2.rb
140
154
  - benchmarks/generation_bm.rb
141
155
  - benchmarks/rack_mount.rb
@@ -154,7 +168,6 @@ files:
154
168
  - examples/unnamed_variable.ru
155
169
  - examples/variable.ru
156
170
  - examples/variable_with_regex.ru
157
- - ext/gem_rake.rb
158
171
  - http_router.gemspec
159
172
  - lib/ext/rack/rack_mapper.rb
160
173
  - lib/ext/rack/rack_urlmap.rb
data/Tumbler DELETED
@@ -1,4 +0,0 @@
1
- gem_name "http_router"
2
-
3
- version_file 'lib/http_router/version.rb'
4
- changelog_file "CHANGELOG"
@@ -1,126 +0,0 @@
1
- module Bundler
2
- class GemHelper
3
-
4
- def self.install_tasks
5
- dir = caller.find{|c| /Rakefile:/}[/^(.*?)\/Rakefile:/, 1]
6
- GemHelper.new(dir).install
7
- end
8
-
9
- attr_reader :spec_path, :base, :name
10
-
11
- def initialize(base, name = nil)
12
- @base = base
13
- @name = name || interpolate_name
14
- @spec_path = File.join(@base, "#{@name}.gemspec")
15
- end
16
-
17
- def install
18
- desc 'Build your gem into the pkg directory'
19
- task 'build' do
20
- build_gem
21
- end
22
-
23
- desc 'Install your gem into the pkg directory'
24
- task 'install' do
25
- install_gem
26
- end
27
-
28
- desc 'Push your gem to rubygems'
29
- task 'push' do
30
- push_gem
31
- end
32
- end
33
-
34
- def build_gem
35
- file_name = nil
36
- sh("gem build #{spec_path}") {
37
- file_name = File.basename(built_gem_path)
38
- FileUtils.mkdir_p(File.join(base, 'pkg'))
39
- FileUtils.mv(built_gem_path, 'pkg')
40
- }
41
- File.join(base, 'pkg', file_name)
42
- end
43
-
44
- def install_gem
45
- built_gem_path = build_gem
46
- sh("gem install #{built_gem_path}")
47
- end
48
-
49
- def push_gem
50
- guard_clean
51
- guard_already_tagged
52
- tag_version {
53
- git_push
54
- rubygem_push(build_gem)
55
- }
56
- end
57
-
58
- protected
59
- def rubygem_push(path)
60
- sh("gem push #{path}")
61
- end
62
-
63
- def built_gem_path
64
- Dir[File.join(base, "#{name}-*.gem")].sort_by{|f| File.mtime(f)}.last
65
- end
66
-
67
- def interpolate_name
68
- gemspecs = Dir[File.join(base, "*.gemspec")]
69
- raise "Unable to determine name from existing gemspec." unless gemspecs.size == 1
70
-
71
- File.basename(gemspecs.first)[/^(.*)\.gemspec$/, 1]
72
- end
73
-
74
- def git_push
75
- sh "git push --all"
76
- sh "git push --tags"
77
- end
78
-
79
- def guard_already_tagged
80
- sh('git tag').split(/\n/).include?(current_version_tag) and raise("This tag has already been committed to the repo.")
81
- end
82
-
83
- def guard_clean
84
- clean? or raise("There are files that need to be committed first.")
85
- end
86
-
87
- def clean?
88
- sh("git ls-files -dm").split("\n").size.zero?
89
- end
90
-
91
- def tag_version
92
- sh "git tag #{current_version_tag}"
93
- yield if block_given?
94
- rescue
95
- sh "git tag -d #{current_version_tag}"
96
- raise
97
- end
98
-
99
- def current_version
100
- raise("Version file could not be found at #{version_file_path}") unless File.exist?(version_file_path)
101
- File.read(version_file_path)[/V(ERSION|ersion)\s*=\s*(["'])(.*?)\2/, 3]
102
- end
103
-
104
- def version_file_path
105
- File.join(base, 'lib', name, 'version.rb')
106
- end
107
-
108
- def current_version_tag
109
- "v#{current_version}"
110
- end
111
-
112
- def sh(cmd, &block)
113
- output, code = sh_with_code(cmd, &block)
114
- code == 0 ? output : raise(output)
115
- end
116
-
117
- def sh_with_code(cmd, &block)
118
- output = ''
119
- Dir.chdir(base) {
120
- output = `#{cmd}`
121
- block.call if block and $? == 0
122
- }
123
- [output, $?]
124
- end
125
- end
126
- end