lgierth-rack-mount 0.6.13
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +36 -0
- data/lib/rack/mount.rb +32 -0
- data/lib/rack/mount/analysis/frequency.rb +60 -0
- data/lib/rack/mount/analysis/histogram.rb +74 -0
- data/lib/rack/mount/analysis/splitting.rb +159 -0
- data/lib/rack/mount/code_generation.rb +117 -0
- data/lib/rack/mount/generatable_regexp.rb +210 -0
- data/lib/rack/mount/multimap.rb +53 -0
- data/lib/rack/mount/prefix.rb +36 -0
- data/lib/rack/mount/regexp_with_named_groups.rb +69 -0
- data/lib/rack/mount/route.rb +130 -0
- data/lib/rack/mount/route_set.rb +420 -0
- data/lib/rack/mount/strexp.rb +68 -0
- data/lib/rack/mount/strexp/parser.rb +160 -0
- data/lib/rack/mount/strexp/parser.y +34 -0
- data/lib/rack/mount/strexp/tokenizer.rb +83 -0
- data/lib/rack/mount/strexp/tokenizer.rex +12 -0
- data/lib/rack/mount/utils.rb +162 -0
- data/lib/rack/mount/vendor/multimap/multimap.rb +569 -0
- data/lib/rack/mount/vendor/multimap/multiset.rb +185 -0
- data/lib/rack/mount/vendor/multimap/nested_multimap.rb +158 -0
- data/lib/rack/mount/vendor/regin/regin.rb +75 -0
- data/lib/rack/mount/vendor/regin/regin/alternation.rb +40 -0
- data/lib/rack/mount/vendor/regin/regin/anchor.rb +4 -0
- data/lib/rack/mount/vendor/regin/regin/atom.rb +54 -0
- data/lib/rack/mount/vendor/regin/regin/character.rb +51 -0
- data/lib/rack/mount/vendor/regin/regin/character_class.rb +50 -0
- data/lib/rack/mount/vendor/regin/regin/collection.rb +77 -0
- data/lib/rack/mount/vendor/regin/regin/expression.rb +126 -0
- data/lib/rack/mount/vendor/regin/regin/group.rb +85 -0
- data/lib/rack/mount/vendor/regin/regin/options.rb +55 -0
- data/lib/rack/mount/vendor/regin/regin/parser.rb +520 -0
- data/lib/rack/mount/vendor/regin/regin/tokenizer.rb +246 -0
- data/lib/rack/mount/vendor/regin/regin/version.rb +3 -0
- data/lib/rack/mount/version.rb +3 -0
- metadata +140 -0
@@ -0,0 +1,160 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.4.6
|
4
|
+
# from Racc grammer file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
|
9
|
+
require 'rack/mount/utils'
|
10
|
+
require 'rack/mount/strexp/tokenizer'
|
11
|
+
|
12
|
+
module Rack
|
13
|
+
module Mount
|
14
|
+
class StrexpParser < Racc::Parser
|
15
|
+
|
16
|
+
|
17
|
+
if Regin.regexp_supports_named_captures?
|
18
|
+
REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze
|
19
|
+
else
|
20
|
+
REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_accessor :anchor, :requirements
|
24
|
+
##### State transition tables begin ###
|
25
|
+
|
26
|
+
racc_action_table = [
|
27
|
+
1, 2, 3, 9, 4, 1, 2, 3, 12, 4,
|
28
|
+
1, 2, 3, 11, 4, 1, 2, 3, nil, 4 ]
|
29
|
+
|
30
|
+
racc_action_check = [
|
31
|
+
0, 0, 0, 5, 0, 3, 3, 3, 9, 3,
|
32
|
+
8, 8, 8, 8, 8, 6, 6, 6, nil, 6 ]
|
33
|
+
|
34
|
+
racc_action_pointer = [
|
35
|
+
-2, nil, nil, 3, nil, 3, 13, nil, 8, 8,
|
36
|
+
nil, nil, nil ]
|
37
|
+
|
38
|
+
racc_action_default = [
|
39
|
+
-8, -4, -5, -8, -7, -8, -1, -3, -8, -8,
|
40
|
+
-2, -6, 13 ]
|
41
|
+
|
42
|
+
racc_goto_table = [
|
43
|
+
6, 5, 10, 8, 10 ]
|
44
|
+
|
45
|
+
racc_goto_check = [
|
46
|
+
2, 1, 3, 2, 3 ]
|
47
|
+
|
48
|
+
racc_goto_pointer = [
|
49
|
+
nil, 1, 0, -4 ]
|
50
|
+
|
51
|
+
racc_goto_default = [
|
52
|
+
nil, nil, nil, 7 ]
|
53
|
+
|
54
|
+
racc_reduce_table = [
|
55
|
+
0, 0, :racc_error,
|
56
|
+
1, 8, :_reduce_1,
|
57
|
+
2, 9, :_reduce_2,
|
58
|
+
1, 9, :_reduce_none,
|
59
|
+
1, 10, :_reduce_4,
|
60
|
+
1, 10, :_reduce_5,
|
61
|
+
3, 10, :_reduce_6,
|
62
|
+
1, 10, :_reduce_7 ]
|
63
|
+
|
64
|
+
racc_reduce_n = 8
|
65
|
+
|
66
|
+
racc_shift_n = 13
|
67
|
+
|
68
|
+
racc_token_table = {
|
69
|
+
false => 0,
|
70
|
+
:error => 1,
|
71
|
+
:PARAM => 2,
|
72
|
+
:GLOB => 3,
|
73
|
+
:LPAREN => 4,
|
74
|
+
:RPAREN => 5,
|
75
|
+
:CHAR => 6 }
|
76
|
+
|
77
|
+
racc_nt_base = 7
|
78
|
+
|
79
|
+
racc_use_result_var = true
|
80
|
+
|
81
|
+
Racc_arg = [
|
82
|
+
racc_action_table,
|
83
|
+
racc_action_check,
|
84
|
+
racc_action_default,
|
85
|
+
racc_action_pointer,
|
86
|
+
racc_goto_table,
|
87
|
+
racc_goto_check,
|
88
|
+
racc_goto_default,
|
89
|
+
racc_goto_pointer,
|
90
|
+
racc_nt_base,
|
91
|
+
racc_reduce_table,
|
92
|
+
racc_token_table,
|
93
|
+
racc_shift_n,
|
94
|
+
racc_reduce_n,
|
95
|
+
racc_use_result_var ]
|
96
|
+
|
97
|
+
Racc_token_to_s_table = [
|
98
|
+
"$end",
|
99
|
+
"error",
|
100
|
+
"PARAM",
|
101
|
+
"GLOB",
|
102
|
+
"LPAREN",
|
103
|
+
"RPAREN",
|
104
|
+
"CHAR",
|
105
|
+
"$start",
|
106
|
+
"target",
|
107
|
+
"expr",
|
108
|
+
"token" ]
|
109
|
+
|
110
|
+
Racc_debug_parser = false
|
111
|
+
|
112
|
+
##### State transition tables end #####
|
113
|
+
|
114
|
+
# reduce 0 omitted
|
115
|
+
|
116
|
+
def _reduce_1(val, _values, result)
|
117
|
+
result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}"
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
def _reduce_2(val, _values, result)
|
122
|
+
result = val.join
|
123
|
+
result
|
124
|
+
end
|
125
|
+
|
126
|
+
# reduce 3 omitted
|
127
|
+
|
128
|
+
def _reduce_4(val, _values, result)
|
129
|
+
name = val[0].to_sym
|
130
|
+
requirement = requirements[name]
|
131
|
+
result = REGEXP_NAMED_CAPTURE % [name, requirement]
|
132
|
+
|
133
|
+
result
|
134
|
+
end
|
135
|
+
|
136
|
+
def _reduce_5(val, _values, result)
|
137
|
+
name = val[0].to_sym
|
138
|
+
requirement = requirements[name]
|
139
|
+
result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement]
|
140
|
+
|
141
|
+
result
|
142
|
+
end
|
143
|
+
|
144
|
+
def _reduce_6(val, _values, result)
|
145
|
+
result = "(?:#{val[1]})?"
|
146
|
+
result
|
147
|
+
end
|
148
|
+
|
149
|
+
def _reduce_7(val, _values, result)
|
150
|
+
result = Regexp.escape(val[0])
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def _reduce_none(val, _values, result)
|
155
|
+
val[0]
|
156
|
+
end
|
157
|
+
|
158
|
+
end # class StrexpParser
|
159
|
+
end # module Mount
|
160
|
+
end # module Rack
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Rack::Mount::StrexpParser
|
2
|
+
rule
|
3
|
+
target: expr { result = anchor ? "\\A#{val.join}\\Z" : "\\A#{val.join}" }
|
4
|
+
|
5
|
+
expr: expr token { result = val.join }
|
6
|
+
| token
|
7
|
+
|
8
|
+
token: PARAM {
|
9
|
+
name = val[0].to_sym
|
10
|
+
requirement = requirements[name]
|
11
|
+
result = REGEXP_NAMED_CAPTURE % [name, requirement]
|
12
|
+
}
|
13
|
+
| GLOB {
|
14
|
+
name = val[0].to_sym
|
15
|
+
requirement = requirements[name]
|
16
|
+
result = REGEXP_NAMED_CAPTURE % [name, '.+' || requirement]
|
17
|
+
}
|
18
|
+
| LPAREN expr RPAREN { result = "(?:#{val[1]})?" }
|
19
|
+
| CHAR { result = Regexp.escape(val[0]) }
|
20
|
+
end
|
21
|
+
|
22
|
+
---- header ----
|
23
|
+
require 'rack/mount/utils'
|
24
|
+
require 'rack/mount/strexp/tokenizer'
|
25
|
+
|
26
|
+
---- inner
|
27
|
+
|
28
|
+
if Regin.regexp_supports_named_captures?
|
29
|
+
REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze
|
30
|
+
else
|
31
|
+
REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_accessor :anchor, :requirements
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#--
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by rex 1.0.5.beta1
|
4
|
+
# from lexical definition file "lib/rack/mount/strexp/tokenizer.rex".
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
class Rack::Mount::StrexpParser < Racc::Parser
|
9
|
+
require 'strscan'
|
10
|
+
|
11
|
+
class ScanError < StandardError ; end
|
12
|
+
|
13
|
+
attr_reader :lineno
|
14
|
+
attr_reader :filename
|
15
|
+
attr_accessor :state
|
16
|
+
|
17
|
+
def scan_setup(str)
|
18
|
+
@ss = StringScanner.new(str)
|
19
|
+
@lineno = 1
|
20
|
+
@state = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def action
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
|
27
|
+
def scan_str(str)
|
28
|
+
scan_setup(str)
|
29
|
+
do_parse
|
30
|
+
end
|
31
|
+
alias :scan :scan_str
|
32
|
+
|
33
|
+
def load_file( filename )
|
34
|
+
@filename = filename
|
35
|
+
open(filename, "r") do |f|
|
36
|
+
scan_setup(f.read)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def scan_file( filename )
|
41
|
+
load_file(filename)
|
42
|
+
do_parse
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def next_token
|
47
|
+
return if @ss.eos?
|
48
|
+
|
49
|
+
text = @ss.peek(1)
|
50
|
+
@lineno += 1 if text == "\n"
|
51
|
+
token = case @state
|
52
|
+
when nil
|
53
|
+
case
|
54
|
+
when (text = @ss.scan(/\\(\(|\)|:|\*)/))
|
55
|
+
action { [:CHAR, @ss[1]] }
|
56
|
+
|
57
|
+
when (text = @ss.scan(/\:([a-zA-Z_]\w*)/))
|
58
|
+
action { [:PARAM, @ss[1]] }
|
59
|
+
|
60
|
+
when (text = @ss.scan(/\*([a-zA-Z_]\w*)/))
|
61
|
+
action { [:GLOB, @ss[1]] }
|
62
|
+
|
63
|
+
when (text = @ss.scan(/\(/))
|
64
|
+
action { [:LPAREN, text] }
|
65
|
+
|
66
|
+
when (text = @ss.scan(/\)/))
|
67
|
+
action { [:RPAREN, text] }
|
68
|
+
|
69
|
+
when (text = @ss.scan(/./))
|
70
|
+
action { [:CHAR, text] }
|
71
|
+
|
72
|
+
else
|
73
|
+
text = @ss.string[@ss.pos .. -1]
|
74
|
+
raise ScanError, "can not match: '" + text + "'"
|
75
|
+
end # if
|
76
|
+
|
77
|
+
else
|
78
|
+
raise ScanError, "undefined state: '" + state.to_s + "'"
|
79
|
+
end # case state
|
80
|
+
token
|
81
|
+
end # def next_token
|
82
|
+
|
83
|
+
end # class
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Rack::Mount::StrexpParser
|
2
|
+
macro
|
3
|
+
RESERVED \(|\)|:|\*
|
4
|
+
ALPHA_U [a-zA-Z_]
|
5
|
+
rule
|
6
|
+
\\({RESERVED}) { [:CHAR, @ss[1]] }
|
7
|
+
\:({ALPHA_U}\w*) { [:PARAM, @ss[1]] }
|
8
|
+
\*({ALPHA_U}\w*) { [:GLOB, @ss[1]] }
|
9
|
+
\( { [:LPAREN, text] }
|
10
|
+
\) { [:RPAREN, text] }
|
11
|
+
. { [:CHAR, text] }
|
12
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
begin
|
2
|
+
require 'regin'
|
3
|
+
rescue LoadError
|
4
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/regin'))
|
5
|
+
require 'regin'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module Rack::Mount
|
11
|
+
# Private utility methods used throughout Rack::Mount.
|
12
|
+
#--
|
13
|
+
# This module is a trash can. Try to move these functions into
|
14
|
+
# more appropriate contexts.
|
15
|
+
#++
|
16
|
+
module Utils
|
17
|
+
def silence_debug
|
18
|
+
old_debug, $DEBUG = $DEBUG, nil
|
19
|
+
yield
|
20
|
+
ensure
|
21
|
+
$DEBUG = old_debug
|
22
|
+
end
|
23
|
+
module_function :silence_debug
|
24
|
+
|
25
|
+
def debug(msg)
|
26
|
+
warn "Rack::Mount #{msg}" if $DEBUG
|
27
|
+
end
|
28
|
+
module_function :debug
|
29
|
+
|
30
|
+
# Normalizes URI path.
|
31
|
+
#
|
32
|
+
# Strips off trailing slash and ensures there is a leading slash.
|
33
|
+
#
|
34
|
+
# normalize_path("/foo") # => "/foo"
|
35
|
+
# normalize_path("/foo/") # => "/foo"
|
36
|
+
# normalize_path("foo") # => "/foo"
|
37
|
+
# normalize_path("") # => "/"
|
38
|
+
def normalize_path(path)
|
39
|
+
path = "/#{path}"
|
40
|
+
path.squeeze!('/')
|
41
|
+
path.sub!(%r{/+\Z}, '')
|
42
|
+
path = '/' if path == ''
|
43
|
+
path
|
44
|
+
end
|
45
|
+
module_function :normalize_path
|
46
|
+
|
47
|
+
# Removes trailing nils from array.
|
48
|
+
#
|
49
|
+
# pop_trailing_blanks!([1, 2, 3]) # => [1, 2, 3]
|
50
|
+
# pop_trailing_blanks!([1, 2, 3, nil, ""]) # => [1, 2, 3]
|
51
|
+
# pop_trailing_blanks!([nil]) # => []
|
52
|
+
# pop_trailing_blanks!([""]) # => []
|
53
|
+
def pop_trailing_blanks!(ary)
|
54
|
+
while ary.length > 0 && (ary.last.nil? || ary.last == '')
|
55
|
+
ary.pop
|
56
|
+
end
|
57
|
+
ary
|
58
|
+
end
|
59
|
+
module_function :pop_trailing_blanks!
|
60
|
+
|
61
|
+
RESERVED_PCHAR = ':@&=+$,;%'
|
62
|
+
SAFE_PCHAR = "#{URI::REGEXP::PATTERN::UNRESERVED}#{RESERVED_PCHAR}"
|
63
|
+
if RUBY_VERSION >= '1.9'
|
64
|
+
UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false).freeze
|
65
|
+
else
|
66
|
+
UNSAFE_PCHAR = Regexp.new("[^#{SAFE_PCHAR}]", false, 'N').freeze
|
67
|
+
end
|
68
|
+
|
69
|
+
Parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
70
|
+
|
71
|
+
def escape_uri(uri)
|
72
|
+
Parser.escape(uri.to_s, UNSAFE_PCHAR)
|
73
|
+
end
|
74
|
+
module_function :escape_uri
|
75
|
+
|
76
|
+
if ''.respond_to?(:force_encoding)
|
77
|
+
def unescape_uri(uri)
|
78
|
+
Parser.unescape(uri).force_encoding('utf-8')
|
79
|
+
end
|
80
|
+
else
|
81
|
+
def unescape_uri(uri)
|
82
|
+
URI.unescape(uri)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
module_function :unescape_uri
|
86
|
+
|
87
|
+
# Taken from Rack 1.1.x to build nested query strings
|
88
|
+
def build_nested_query(value, prefix = nil) #:nodoc:
|
89
|
+
case value
|
90
|
+
when Array
|
91
|
+
value.map { |v|
|
92
|
+
build_nested_query(v, "#{prefix}[]")
|
93
|
+
}.join("&")
|
94
|
+
when Hash
|
95
|
+
value.map { |k, v|
|
96
|
+
build_nested_query(v, prefix ? "#{prefix}[#{Rack::Utils.escape(k)}]" : Rack::Utils.escape(k))
|
97
|
+
}.join("&")
|
98
|
+
when String
|
99
|
+
raise ArgumentError, "value must be a Hash" if prefix.nil?
|
100
|
+
"#{prefix}=#{Rack::Utils.escape(value)}"
|
101
|
+
else
|
102
|
+
prefix
|
103
|
+
end
|
104
|
+
end
|
105
|
+
module_function :build_nested_query
|
106
|
+
|
107
|
+
# Determines whether the regexp must match the entire string.
|
108
|
+
#
|
109
|
+
# regexp_anchored?(/^foo$/) # => true
|
110
|
+
# regexp_anchored?(/foo/) # => false
|
111
|
+
# regexp_anchored?(/^foo/) # => false
|
112
|
+
# regexp_anchored?(/foo$/) # => false
|
113
|
+
def regexp_anchored?(regexp)
|
114
|
+
regexp.source =~ /\A(\\A|\^).*(\\Z|\$)\Z/m ? true : false
|
115
|
+
end
|
116
|
+
module_function :regexp_anchored?
|
117
|
+
|
118
|
+
def normalize_extended_expression(regexp)
|
119
|
+
return regexp unless regexp.options & Regexp::EXTENDED != 0
|
120
|
+
source = regexp.source
|
121
|
+
source.gsub!(/#.+$/, '')
|
122
|
+
source.gsub!(/\s+/, '')
|
123
|
+
source.gsub!(/\\\//, '/')
|
124
|
+
Regexp.compile(source)
|
125
|
+
end
|
126
|
+
module_function :normalize_extended_expression
|
127
|
+
|
128
|
+
def parse_regexp(regexp)
|
129
|
+
cache = @@_parse_regexp_cache ||= {}
|
130
|
+
|
131
|
+
if expression = cache[regexp]
|
132
|
+
return expression
|
133
|
+
end
|
134
|
+
|
135
|
+
unless regexp.is_a?(RegexpWithNamedGroups)
|
136
|
+
regexp = RegexpWithNamedGroups.new(regexp)
|
137
|
+
end
|
138
|
+
|
139
|
+
expression = Regin.parse(regexp)
|
140
|
+
|
141
|
+
unless Regin.regexp_supports_named_captures?
|
142
|
+
tag_captures = Proc.new do |group|
|
143
|
+
case group
|
144
|
+
when Regin::Group
|
145
|
+
# TODO: dup instead of mutating
|
146
|
+
group.instance_variable_set('@name', regexp.names[group.index]) if group.index
|
147
|
+
tag_captures.call(group.expression)
|
148
|
+
when Regin::Expression
|
149
|
+
group.each { |child| tag_captures.call(child) }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
tag_captures.call(expression)
|
153
|
+
end
|
154
|
+
|
155
|
+
cache[regexp] = expression.freeze
|
156
|
+
expression
|
157
|
+
rescue Racc::ParseError, Regin::Parser::ScanError
|
158
|
+
[]
|
159
|
+
end
|
160
|
+
module_function :parse_regexp
|
161
|
+
end
|
162
|
+
end
|