http_router 0.3.10 → 0.3.11

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