pendragon 0.6.2 → 1.0.0

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.
@@ -1,93 +0,0 @@
1
- require 'mustermann/sinatra'
2
-
3
- module Pendragon
4
- # A class for path matching
5
- #
6
- # @example
7
- # matcher = Pendragon::Matcher.new("/category/:id", capture: {id: /\d+/})
8
- # matcher.match("/category/1234") #=> #<MatchData "/category/1234" id:"1234">
9
- #
10
- # @!visibility private
11
- class Matcher
12
- # A character of path delimiter
13
- PATH_DELIMITER = "/".freeze
14
-
15
- # A prefix character of query string
16
- QUERY_PREFIX = "?".freeze
17
-
18
- # A character of query string delimiter
19
- QUERY_DELIMITER = "&".freeze
20
-
21
- # Constructs a new instance of Pendragon::Matcher
22
- # @param [String] path The path is string or regexp.
23
- # @option options [Hash] :capture Set capture for path pattern.
24
- # @option options [Hash] :default_values Set default_values for path pattern.
25
- # @return [Pendragon::Matcher]
26
- def initialize(path, options = {})
27
- @path = path.is_a?(String) && path.empty? ? PATH_DELIMITER : path
28
- @capture = options.delete(:capture)
29
- @default_values = options.delete(:default_values)
30
- end
31
-
32
- # Does the matching.
33
- # @param [String] pattern The pattern is actual path (path_info etc).
34
- # @return [MatchData] If the pattern matched this route, return a MatchData.
35
- # @return [Nil] If the pattern doesn't matched this route, return a nil.
36
- def match(pattern)
37
- match_data = handler.match(pattern)
38
- return match_data if match_data
39
- pattern = pattern[0..-2] if mustermann? && pattern != PATH_DELIMITER && pattern.end_with?(PATH_DELIMITER)
40
- handler.match(pattern)
41
- end
42
-
43
- # Expands a path with params.
44
- # @param [Hash] params The params for path pattern.
45
- # @example
46
- # matcher = Pendragon::Matcher.new("/foo/:bar")
47
- # matcher.expand(:bar => 123) #=> "/foo/123"
48
- # matcher.expand(:bar => "bar", :baz => "test") #=> "/foo/bar?baz=test"
49
- # @return [String] A expaneded path.
50
- def expand(params)
51
- params = params.dup
52
- query = params.keys.inject({}) do |result, key|
53
- result[key] = params.delete(key) if !handler.names.include?(key.to_s)
54
- result
55
- end
56
- params.merge!(@default_values) if @default_values.is_a?(Hash)
57
- expanded_path = handler.expand(params)
58
- expanded_path = expanded_path + QUERY_PREFIX + query.map{|k,v| "#{k}=#{v}" }.join(QUERY_DELIMITER) unless query.empty?
59
- expanded_path
60
- end
61
-
62
- # Returns whether the handler is Mustermann
63
- # @return [Boolean] This matcher's handler is mustermann ?
64
- def mustermann?
65
- handler.instance_of?(Mustermann::Sinatra)
66
- end
67
-
68
- # Returns the handler
69
- # @return [Mustermann::Sinatra] Returns a Mustermann::Sinatra when @path is string.
70
- # @return [Regexp] Returns a regexp when @path is regexp.
71
- def handler
72
- @handler ||=
73
- case @path
74
- when String
75
- Mustermann::Sinatra.new(@path, :capture => @capture)
76
- when Regexp
77
- /^(?:#{@path})$/
78
- end
79
- end
80
-
81
- # Converts the handler into String
82
- # @return [String] Returns a converted handler.
83
- def to_s
84
- handler.to_s
85
- end
86
-
87
- # Returns all named captures
88
- # @return [Array] Returns a named captures.
89
- def names
90
- handler.names
91
- end
92
- end
93
- end
@@ -1,15 +0,0 @@
1
- require 'pendragon/padrino/router'
2
- require 'pendragon/padrino/route'
3
- require 'pendragon/padrino/ext/instance_methods'
4
- require 'pendragon/padrino/ext/class_methods'
5
-
6
- module Pendragon
7
- module Padrino
8
- class << self
9
- def registered(app)
10
- app.extend(ClassMethods)
11
- app.send(:include, InstanceMethods)
12
- end
13
- end
14
- end
15
- end
@@ -1,318 +0,0 @@
1
- module Pendragon
2
- module Padrino
3
- module ClassMethods
4
- CONTENT_TYPE_ALIASES = {:htm => :html} unless defined?(CONTENT_TYPE_ALIASES)
5
- ROUTE_PRIORITY = {:high => 0, :normal => 1, :low => 2} unless defined?(ROUTE_PRIORITY)
6
-
7
- def router
8
- unless @router
9
- @router = ::Pendragon::Padrino::Router.new
10
- @router.configuration = Pendragon::Configuration.new
11
- if settings.respond_to?(:pendragon) && settings.pendragon.instance_of?(Hash)
12
- settings.pendragon.each_pair do |key, value|
13
- @router.configuration.send("#{key}=", value)
14
- end
15
- end
16
- end
17
- block_given? ? yield(@router) : @router
18
- end
19
-
20
- def compiled_router
21
- if @deferred_routes
22
- deferred_routes.each do |routes|
23
- routes.each do |(route, dest)|
24
- route.to(&dest)
25
- route.before_filters.flatten!
26
- route.after_filters.flatten!
27
- end
28
- end
29
- @deferred_routes = nil
30
- end
31
- router
32
- end
33
-
34
- def deferred_routes
35
- @deferred_routes ||= ROUTE_PRIORITY.map{[]}
36
- end
37
-
38
- def url(*args)
39
- params = args.extract_options!
40
- fragment = params.delete(:fragment) || params.delete(:anchor)
41
- path = make_path_with_params(args, value_to_param(params.symbolize_keys))
42
- rebase_url(fragment ? path << '#' << fragment : path)
43
- end
44
- alias :url_for :url
45
-
46
- def make_path_with_params(args, params)
47
- names, params_array = args.partition{ |arg| arg.is_a?(Symbol) }
48
- name = names[0, 2].join(" ").to_sym
49
- compiled_router.path(name, *(params_array << params))
50
- rescue Pendragon::InvalidRouteException
51
- raise ::Padrino::Routing::UnrecognizedException, "Route mapping for url(#{name.inspect}) could not be found"
52
- end
53
-
54
- def recognize_path(path)
55
- responses = @router.recognize_path(path)
56
- [responses[0], responses[1]]
57
- end
58
-
59
- def rebase_url(url)
60
- if url.start_with?('/')
61
- new_url = ''
62
- new_url << conform_uri(ENV['RACK_BASE_URI']) if ENV['RACK_BASE_URI']
63
- new_url << conform_uri(uri_root) if defined?(uri_root)
64
- new_url << url
65
- else
66
- url.blank? ? '/' : url
67
- end
68
- end
69
-
70
- private
71
-
72
- def route(verb, path, *args, &block)
73
- options = case args.size
74
- when 2
75
- args.last.merge(:map => args.first)
76
- when 1
77
- map = args.shift if args.first.is_a?(String)
78
- if args.first.is_a?(Hash)
79
- map ? args.first.merge(:map => map) : args.first
80
- else
81
- {:map => map || args.first}
82
- end
83
- when 0
84
- {}
85
- else raise
86
- end
87
-
88
- route_options = options.dup
89
- route_options[:provides] = @_provides if @_provides
90
- route_options[:accepts] = @_accepts if @_accepts
91
- route_options[:params] = @_params unless @_params.nil? || route_options.include?(:params)
92
-
93
- if protect_from_csrf && (report_csrf_failure || allow_disabled_csrf)
94
- unless route_options.has_key?(:csrf_protection)
95
- route_options[:csrf_protection] = true
96
- end
97
- end
98
-
99
- path, *route_options[:with] = path if path.is_a?(Array)
100
- action = path
101
- path, name, route_parents, options, route_options = *parse_route(path, route_options, verb)
102
- options.reverse_merge!(@_conditions) if @_conditions
103
-
104
- method_name = "#{verb} #{path}"
105
- unbound_method = generate_method(method_name, &block)
106
-
107
- block = block.arity != 0 ?
108
- proc {|a,p| unbound_method.bind(a).call(*p) } :
109
- proc {|a,p| unbound_method.bind(a).call }
110
-
111
- invoke_hook(:route_added, verb, path, block)
112
-
113
- # Pendragon route construction
114
- path[0, 0] = "/" if path == "(.:format)?"
115
- route_options.merge!(:name => name) if name
116
- route = router.add(verb.downcase.to_sym, path, route_options)
117
- route.action = action
118
- priority_name = options.delete(:priority) || :normal
119
- priority = ROUTE_PRIORITY[priority_name] or raise("Priority #{priority_name} not recognized, try #{ROUTE_PRIORITY.keys.join(', ')}")
120
- route.cache = options.key?(:cache) ? options.delete(:cache) : @_cache
121
- route.parent = route_parents ? (route_parents.count == 1 ? route_parents.first : route_parents) : route_parents
122
- route.host = options.delete(:host) if options.key?(:host)
123
- route.user_agent = options.delete(:agent) if options.key?(:agent)
124
- if options.key?(:default_values)
125
- defaults = options.delete(:default_values)
126
- route.options[:default_values] = defaults if defaults
127
- end
128
- options.delete_if do |option, captures|
129
- if route.significant_variable_names.include?(option)
130
- route.capture[option] = Array(captures).first
131
- true
132
- end
133
- end
134
-
135
- # Add Sinatra conditions
136
- options.each {|o, a| route.respond_to?("#{o}=") ? route.send("#{o}=", a) : send(o, *a) }
137
- conditions, @conditions = @conditions, []
138
- route.custom_conditions.concat(conditions)
139
-
140
- invoke_hook(:padrino_route_added, route, verb, path, args, options, block)
141
-
142
- # Add Application defaults
143
- route.before_filters << @filters[:before]
144
- route.after_filters << @filters[:after]
145
- if @_controller
146
- route.use_layout = @layout
147
- route.controller = Array(@_controller)[0].to_s
148
- end
149
-
150
- deferred_routes[priority] << [route, block]
151
-
152
- route
153
- end
154
-
155
- def parse_route(path, options, verb)
156
- route_options = {}
157
-
158
- if options[:params] == true
159
- options.delete(:params)
160
- elsif options.include?(:params)
161
- options[:params] ||= []
162
- options[:params] += options[:with] if options[:with]
163
- end
164
-
165
- # We need check if path is a symbol, if that it's a named route.
166
- map = options.delete(:map)
167
-
168
- # path i.e :index or :show
169
- if path.kind_of?(Symbol)
170
- name = path
171
- path = map ? map.dup : (path == :index ? '/' : path.to_s)
172
- end
173
-
174
- # Build our controller
175
- controller = Array(@_controller).map(&:to_s)
176
-
177
- case path
178
- when String # path i.e "/index" or "/show"
179
- # Now we need to parse our 'with' params
180
- if with_params = options.delete(:with)
181
- path = process_path_for_with_params(path, with_params)
182
- end
183
-
184
- # Now we need to parse our provides
185
- options.delete(:provides) if options[:provides].nil?
186
-
187
- if @_use_format or format_params = options[:provides]
188
- process_path_for_provides(path, format_params)
189
- # options[:add_match_with] ||= {}
190
- # options[:add_match_with][:format] = /[^\.]+/
191
- end
192
-
193
- absolute_map = map && map[0] == ?/
194
-
195
- unless controller.empty?
196
- # Now we need to add our controller path only if not mapped directly
197
- if map.blank? and !absolute_map
198
- controller_path = controller.join("/")
199
- path.gsub!(%r{^\(/\)|/\?}, "")
200
- path = File.join(controller_path, path) unless @_map
201
- end
202
- end
203
-
204
- # Now we need to parse our 'parent' params and parent scope.
205
- if !absolute_map and parent_params = options.delete(:parent) || @_parent
206
- parent_params = (Array(@_parent) + Array(parent_params)).uniq
207
- path = process_path_for_parent_params(path, parent_params)
208
- end
209
-
210
- # Add any controller level map to the front of the path.
211
- path = "#{@_map}/#{path}".squeeze('/') unless absolute_map or @_map.blank?
212
-
213
- # Small reformats
214
- path.gsub!(%r{/\?$}, '(/)') # Remove index path
215
- path.gsub!(%r{//$}, '/') # Remove index path
216
- path[0,0] = "/" if path !~ %r{^\(?/} # Paths must start with a /
217
- path.sub!(%r{/(\))?$}, '\\1') if path != "/" # Remove latest trailing delimiter
218
- path.gsub!(/\/(\(\.|$)/, '\\1') # Remove trailing slashes
219
- path.squeeze!('/')
220
- when Regexp
221
- route_options[:path_for_generation] = options.delete(:generate_with) if options.key?(:generate_with)
222
- end
223
-
224
- name = options.delete(:route_name) if name.nil? && options.key?(:route_name)
225
- name = options.delete(:name) if name.nil? && options.key?(:name)
226
- if name
227
- controller_name = controller.join("_")
228
- name = "#{controller_name} #{name}".to_sym unless controller_name.blank?
229
- end
230
-
231
- # Merge in option defaults.
232
- options.reverse_merge!(:default_values => @_defaults)
233
-
234
- [path, name, parent_params, options, route_options]
235
- end
236
-
237
- def provides(*types)
238
- @_use_format = true
239
- condition do
240
- mime_types = types.map {|t| mime_type(t) }.compact
241
- url_format = params[:format].to_sym if params[:format]
242
- accepts = request.accept.map {|a| a.to_str }
243
- accepts = [] if accepts == ["*/*"]
244
-
245
- # per rfc2616-sec14:
246
- # Assume */* if no ACCEPT header is given.
247
- catch_all = (accepts.delete "*/*" || accepts.empty?)
248
- matching_types = accepts.empty? ? mime_types.slice(0,1) : (accepts & mime_types)
249
- if matching_types.empty? && types.include?(:any)
250
- matching_types = accepts
251
- end
252
-
253
- if !url_format && matching_types.first
254
- type = ::Rack::Mime::MIME_TYPES.find {|k, v| v == matching_types.first }[0].sub(/\./,'').to_sym
255
- accept_format = CONTENT_TYPE_ALIASES[type] || type
256
- elsif catch_all && !types.include?(:any)
257
- type = types.first
258
- accept_format = CONTENT_TYPE_ALIASES[type] || type
259
- end
260
-
261
- matched_format = types.include?(:any) ||
262
- types.include?(accept_format) ||
263
- types.include?(url_format) ||
264
- ((!url_format) && request.accept.empty? && types.include?(:html))
265
- # per rfc2616-sec14:
266
- # answer with 406 if accept is given but types to not match any
267
- # provided type
268
- halt 406 if
269
- (!url_format && !accepts.empty? && !matched_format) ||
270
- (settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept && url_format && !matched_format)
271
-
272
- if matched_format
273
- @_content_type = url_format || accept_format || :html
274
- content_type(@_content_type, :charset => 'utf-8')
275
- end
276
-
277
- matched_format
278
- end
279
- end
280
-
281
- def process_path_for_parent_params(path, parent_params)
282
- parent_prefix = parent_params.flatten.compact.uniq.map do |param|
283
- map = (param.respond_to?(:map) && param.map ? param.map : param.to_s)
284
- part = "#{map}/:#{param.to_s.singularize}_id/"
285
- part = "(#{part})?" if param.respond_to?(:optional) && param.optional?
286
- part
287
- end
288
-
289
- [parent_prefix, path].flatten.join("")
290
- end
291
-
292
- def process_path_for_provides(path, format_params)
293
- path << "(.:format)?" unless path[-11, 11] == '(.:format)?'
294
- end
295
- end
296
- end
297
- end
298
-
299
- if defined?(Padrino) && Padrino::VERSION < '0.12.0'
300
- module Padrino
301
- class Filter
302
- def apply?(request)
303
- detect = @args.any? do |arg|
304
- case arg
305
- when Symbol then request.route_obj && (request.route_obj.name == arg or request.route_obj.name == [@scoped_controller, arg].flatten.join(" ").to_sym)
306
- else arg === request.path_info
307
- end
308
- end || @options.any? do |name, val|
309
- case name
310
- when :agent then val === request.user_agent
311
- else val === request.send(name)
312
- end
313
- end
314
- detect ^ !@mode
315
- end
316
- end
317
- end
318
- end
@@ -1,63 +0,0 @@
1
- module Pendragon
2
- module Padrino
3
- module InstanceMethods
4
- private
5
-
6
- def invoke_route(route, params, options = {})
7
- original_params, parent_layout, successful = @params.dup, @layout, false
8
- captured_params = params[:captures].is_a?(Array) ? params.delete(:captures) :
9
- params.values_at(*route.matcher.names.dup)
10
-
11
- @_response_buffer = nil
12
- @route = request.route_obj = route
13
- @params.merge!(params) if params.is_a?(Hash)
14
- @params.merge!(:captures => captured_params) if !captured_params.empty? && route.path.is_a?(Regexp)
15
- @block_params = params
16
-
17
- filter! :before if options[:first]
18
-
19
- catch(:pass) do
20
- begin
21
- (route.before_filters - settings.filters[:before]).each{|block| instance_eval(&block) }
22
- @layout = route.use_layout if route.use_layout
23
- route.custom_conditions.each {|block| pass if block.bind(self).call == false }
24
- halt_response = catch(:halt){ route_eval{ route.block[self, captured_params] }}
25
- @_response_buffer = halt_response.is_a?(Array) ? halt_response.last : halt_response
26
- successful = true
27
- halt(halt_response)
28
- ensure
29
- (route.after_filters - settings.filters[:after]).each {|block| instance_eval(&block) } if successful
30
- @layout, @params = parent_layout, original_params
31
- end
32
- end
33
- end
34
-
35
- def route!(base = settings, pass_block = nil)
36
- Thread.current['padrino.instance'] = self
37
- code, headers, routes = base.compiled_router.call(@request.env)
38
-
39
- status(code)
40
- if code == 200
41
- routes.each_with_index do |(route, pendragon_params), index|
42
- next if route.user_agent && !(route.user_agent =~ @request.user_agent)
43
- invoke_route(route, pendragon_params, :first => index.zero?)
44
- end
45
- else
46
- route_eval do
47
- headers.each{|k, v| response[k] = v } unless headers.empty?
48
- route_missing if code == 404
49
- route_missing if allow = response['Allow'] and allow.include?(request.env['REQUEST_METHOD'])
50
- end
51
- end
52
-
53
- if base.superclass.respond_to?(:router)
54
- route!(base.superclass, pass_block)
55
- return
56
- end
57
-
58
- route_eval(&pass_block) if pass_block
59
- route_missing
60
- end
61
- end
62
- end
63
- end