Skip to content

Commit

Permalink
Merge branch 'master' into url_mount
Browse files Browse the repository at this point in the history
Conflicts:
	.gitignore
	spec/rack/dispatch_spec.rb
  • Loading branch information
joshbuddy committed Jun 11, 2010
2 parents 2a81688 + f6ad5fd commit 07cc638
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 51 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
pkg
*.gem
.bundle
rdoc
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
0.2.1
0.2.3
3 changes: 2 additions & 1 deletion lib/http_router.rb
Expand Up @@ -9,6 +9,7 @@
require 'http_router/response'
require 'http_router/path'
require 'http_router/optional_compiler'
require 'http_router/parts'

class HttpRouter
# Raised when a Route is not able to be generated.
Expand Down Expand Up @@ -238,7 +239,7 @@ def clone
end

def split(path)
(path[0] == ?/ ? path[1, path.size] : path).split('/')
Parts.new(path)
end

private
Expand Down
8 changes: 4 additions & 4 deletions lib/http_router/glob.rb
@@ -1,13 +1,13 @@
class HttpRouter
class Glob < Variable
def matches?(parts, whole_path)
@matches_with.nil? or (!parts.empty? and match = @matches_with.match(parts.first) and match.begin(0))
def matches?(parts)
@matches_with.nil? or (!parts.empty? and match = @matches_with.match(parts.first) and match.begin(0)) ? match : nil
end

def consume(parts, whole_path)
def consume(match, parts)
if @matches_with
params = [parts.shift]
params << parts.shift while matches?(parts, whole_path)
params << parts.shift while matches?(parts)
params
else
params = parts.dup
Expand Down
23 changes: 13 additions & 10 deletions lib/http_router/node.rb
Expand Up @@ -138,18 +138,24 @@ def generate_request_method_tree(request_options)
end

def find_on_parts(request, parts, params)
unless parts.empty?
whole_path = parts.join('/')
if parts and !parts.empty?
if parts.size == 1 and parts.first == ''
potential_match = find_on_parts(request, [], params)
if potential_match and (router.ignore_trailing_slash? or potential_match.value && potential_match.value.route.trailing_slash_ignore?)
parts.shift
return potential_match
end
end
if @linear && !@linear.empty?
response = nil
dupped_parts = nil
next_node = @linear.find do |(tester, node)|
if tester.respond_to?(:matches?) and tester.matches?(parts, whole_path)
if tester.respond_to?(:matches?) and match = tester.matches?(parts)
dupped_parts = parts.dup
params << tester.consume(dupped_parts, whole_path)
params << tester.consume(match, dupped_parts)
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
elsif tester.respond_to?(:match) and match = tester.match(whole_path) and match.begin(0) == 0
dupped_parts = router.split(whole_path[match[0].size, whole_path.size])
elsif tester.respond_to?(:match) and match = tester.match(parts.whole_path) and match.begin(0) == 0
dupped_parts = router.split(parts.whole_path[match[0].size, parts.whole_path.size])
parts.replace(dupped_parts) if response = node.find_on_parts(request, dupped_parts, params)
else
nil
Expand All @@ -161,11 +167,8 @@ def find_on_parts(request, parts, params)
parts.shift
return match.find_on_parts(request, parts, params)
elsif @catchall
params << @catchall.variable.consume(parts, whole_path)
params << @catchall.variable.consume(nil, parts)
return @catchall.find_on_parts(request, parts, params)
elsif parts.size == 1 && parts.first == '' && (value && value.route.trailing_slash_ignore? || router.ignore_trailing_slash?)
parts.shift
return find_on_parts(request, parts, params)
end
end
if request_node
Expand Down
2 changes: 1 addition & 1 deletion lib/http_router/optional_compiler.rb
Expand Up @@ -5,7 +5,7 @@ def initialize(path)
@start_index = 0
@end_index = 1
@paths = [""]
@chars = path.chars.to_a
@chars = path.split('')
while !@chars.empty?
case @chars.first
when '(' then @chars.shift and double_paths
Expand Down
21 changes: 21 additions & 0 deletions lib/http_router/parts.rb
@@ -0,0 +1,21 @@
class HttpRouter
class Parts < Array
def initialize(path)
super((path[0] == ?/ ? path[1, path.size] : path).split('/'))
end

def whole_path
@whole_path ||= join('/')
end

def shift
@whole_path = nil
super
end

def replace(ary)
@whole_path = nil
super
end
end
end
5 changes: 2 additions & 3 deletions lib/http_router/path.rb
@@ -1,4 +1,3 @@
require 'cgi'
class HttpRouter
class Path
attr_reader :parts, :route
Expand Down Expand Up @@ -58,9 +57,9 @@ def generate_querystring(uri, params)
params.each do |k,v|
case v
when Array
v.each { |v_part| uri << '&' << CGI.escape(k.to_s) << '%5B%5D=' << CGI.escape(v_part.to_s) }
v.each { |v_part| uri << '&' << Rack::Utils.escape(k.to_s) << '%5B%5D=' << Rack::Utils.escape(v_part.to_s) }
else
uri << '&' << CGI.escape(k.to_s) << '=' << CGI.escape(v.to_s)
uri << '&' << Rack::Utils.escape(k.to_s) << '=' << Rack::Utils.escape(v.to_s)
end
end
uri[uri_size] = ??
Expand Down
3 changes: 2 additions & 1 deletion lib/http_router/route.rb
Expand Up @@ -108,6 +108,7 @@ def condition(conditions)
@conditions.key?(k) ?
@conditions[k] << v :
@conditions[k] = Array(v)
@conditions[k].flatten!
end
self
end
Expand Down Expand Up @@ -318,7 +319,7 @@ def generate_interstitial_parts(part)
scan_regex = if next_index == part_segments.size
matcher || /^[^\/]+/
else
/^#{matcher || '.*?'}(?=#{Regexp.quote(part_segments[next_index])})/
/^#{matcher || '[^\/]*?'}(?=#{Regexp.quote(part_segments[next_index])})/
end
router.variable(v_name, scan_regex)
else
Expand Down
9 changes: 4 additions & 5 deletions lib/http_router/variable.rb
Expand Up @@ -8,14 +8,13 @@ def initialize(router, name, matches_with = nil)
@matches_with = matches_with
end

def matches?(parts, whole_path)
@matches_with.nil? or (@matches_with and match = @matches_with.match(whole_path) and match.begin(0) == 0)
def matches?(parts)
@matches_with.nil? or (@matches_with and match = @matches_with.match(parts.whole_path) and match.begin(0) == 0) ? match : nil
end

def consume(parts, whole_path)
def consume(match, parts)
if @matches_with
match = @matches_with.match(whole_path)
parts.replace(router.split(whole_path[match.end(0), whole_path.size]))
parts.replace(router.split(parts.whole_path[match.end(0), parts.whole_path.size]))
match[0]
else
parts.shift
Expand Down
46 changes: 21 additions & 25 deletions spec/rack/dispatch_spec.rb
@@ -1,8 +1,3 @@
require 'spec_helper'

route_set = HttpRouter.new
route_set.extend(CallWithMockRequestMixin)

describe "HttpRouter route dispatching with redirect_on_trailing_delimiters" do
before(:each) do
@route_set = HttpRouter.new(:redirect_trailing_slash => true)
Expand All @@ -20,78 +15,79 @@

describe "HttpRouter route dispatching" do
before(:each) do
route_set.reset!
@route_set = HttpRouter.new(:redirect_trailing_slash => true)
@route_set.extend(CallWithMockRequestMixin)
@app = MockApp.new("Hello World!")
end

describe "HTTP GET" do
before(:each) do
route_set.reset!
route_set.add('/sample').request_method('GET').to(@app)
@route_set.reset!
@route_set.add('/sample').request_method('GET').to(@app)
end

it "should dispatch a request" do
response = route_set.call_with_mock_request
response = @route_set.call_with_mock_request
response.body.should eql("Hello World!")
end

it "should write router.params" do
response = route_set.call_with_mock_request
response = @route_set.call_with_mock_request
@app.env["router.params"].should == {}
end
end

describe "HTTP POST" do
before(:each) do
route_set.reset!
route_set.add('/sample').post.to(@app)
route_set.add('/sample').to(MockApp.new("You shouldn't get here if you are using POST"))
@route_set.reset!
@route_set.add('/sample').post.to(@app)
@route_set.add('/sample').to(MockApp.new("You shouldn't get here if you are using POST"))
end

it "should dispatch a POST request" do
response = route_set.call_with_mock_request('/sample', 'POST')
response = @route_set.call_with_mock_request('/sample', 'POST')
response.body.should eql("Hello World!")
end

it "shouldn't dispatch a GET request" do
response = route_set.call_with_mock_request('/sample', 'GET')
response = @route_set.call_with_mock_request('/sample', 'GET')
response.body.should eql("You shouldn't get here if you are using POST")
end

it "should write router.params" do
response = route_set.call_with_mock_request("/sample", 'POST')
response = @route_set.call_with_mock_request("/sample", 'POST')
@app.env["router.params"].should == {}
end
end

it "should returns HTTP 405 if the method mis-matches" do
route_set.reset!
route_set.post('/sample').to(@app)
route_set.put('/sample').to(@app)
response = route_set.call_with_mock_request('/sample', 'GET')
@route_set.reset!
@route_set.post('/sample').to(@app)
@route_set.put('/sample').to(@app)
response = @route_set.call_with_mock_request('/sample', 'GET')
response.status.should eql(405)
response['Allow'].should == 'POST, PUT'
end

it "should returns HTTP 404 if route doesn't exist" do
response = route_set.call_with_mock_request("/not-existing-url")
response = @route_set.call_with_mock_request("/not-existing-url")
response.status.should eql(404)
end

describe "shortcuts" do
describe "get" do
before(:each) do
route_set.reset!
route_set.get('/sample').to(@app)
@route_set.reset!
@route_set.get('/sample').head.to(@app)
end

it "should dispatch a GET request" do
response = route_set.call_with_mock_request("/sample", "GET")
response = @route_set.call_with_mock_request("/sample", "GET")
response.body.should eql("Hello World!")
end

it "should dispatch a HEAD request" do
response = route_set.call_with_mock_request("/sample", "HEAD")
response = @route_set.call_with_mock_request("/sample", "HEAD")
response.body.should eql("Hello World!")
end
end
Expand Down

0 comments on commit 07cc638

Please sign in to comment.