pendragon 0.6.2 → 1.0.0

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