padrino-core 0.12.2 → 0.12.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/padrino-core/application/application_setup.rb +3 -4
- data/lib/padrino-core/application/routing.rb +133 -380
- data/lib/padrino-core/application.rb +17 -24
- data/lib/padrino-core/cli/base.rb +2 -90
- data/lib/padrino-core/cli/launcher.rb +95 -0
- data/lib/padrino-core/ext/http_router.rb +181 -0
- data/lib/padrino-core/ext/sinatra.rb +29 -0
- data/lib/padrino-core/filter.rb +47 -0
- data/lib/padrino-core/loader.rb +27 -50
- data/lib/padrino-core/reloader.rb +63 -23
- data/lib/padrino-core/server.rb +3 -1
- data/lib/padrino-core/version.rb +1 -1
- data/padrino-core.gemspec +1 -1
- data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
- data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
- data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
- data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
- data/test/test_core.rb +1 -0
- data/test/test_logger.rb +39 -11
- data/test/test_reloader_system.rb +57 -1
- data/test/test_routing.rb +12 -0
- metadata +18 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0c4e1103a6097258ff654c266fbc979a4115409
|
4
|
+
data.tar.gz: be1ce195a701fc3a868069bdfee1847d87bfedfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 08c3823803340970a7c3e5138e0705439a7db34880f075de1f886725ac44792d1cba96f7c396aadb4f2fa7e153313dda9611468721a66d71bc80c4a9c4e31630
|
7
|
+
data.tar.gz: cf6e3a2954d7541a981318094e9600d266a593189852b3028a91d3c9316b03a39b2719087e231eac55f800ca65be5f9a7d455d55b9f2083f0ddbf462df1ccd8b
|
@@ -23,10 +23,9 @@ module Padrino
|
|
23
23
|
set :default_builder, 'StandardFormBuilder'
|
24
24
|
|
25
25
|
# TODO: Remove this hack after getting rid of thread-unsafe http_router:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
set :add_charset, %w[javascript xml xhtml+xml].map{ |type| "application/#{type}" }
|
26
|
+
if RUBY_PLATFORM == "java"
|
27
|
+
set :init_mutex, Mutex.new
|
28
|
+
end
|
30
29
|
|
31
30
|
default_paths
|
32
31
|
default_security
|
@@ -1,261 +1,9 @@
|
|
1
|
-
require 'http_router' unless defined?(HttpRouter)
|
2
1
|
require 'padrino-support'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
class Sinatra::Request
|
8
|
-
attr_accessor :route_obj
|
9
|
-
|
10
|
-
def controller
|
11
|
-
route_obj && route_obj.controller
|
12
|
-
end
|
13
|
-
def action
|
14
|
-
route_obj && route_obj.action
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# This patches Sinatra to accept UTF-8 urls on JRuby 1.7.6
|
20
|
-
#
|
21
|
-
if RUBY_ENGINE == 'jruby' && defined?(JRUBY_VERSION) && JRUBY_VERSION > '1.7.4'
|
22
|
-
class Sinatra::Base
|
23
|
-
class << self
|
24
|
-
alias_method :old_generate_method, :generate_method
|
25
|
-
def generate_method(method_name, &block)
|
26
|
-
old_generate_method(method_name.to_sym, &block)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class HttpRouter
|
33
|
-
def rewrite_partial_path_info(env, request); end
|
34
|
-
def rewrite_path_info(env, request); end
|
35
|
-
|
36
|
-
def process_destination_path(path, env)
|
37
|
-
Thread.current['padrino.instance'].instance_eval do
|
38
|
-
request.route_obj = path.route
|
39
|
-
@_response_buffer = nil
|
40
|
-
@route = path.route
|
41
|
-
@params ||= {}
|
42
|
-
@params.update(env['router.params'])
|
43
|
-
@block_params = if match_data = env['router.request'].extra_env['router.regex_match']
|
44
|
-
params_list = match_data.to_a
|
45
|
-
params_list.shift
|
46
|
-
@params[:captures] = params_list
|
47
|
-
params_list
|
48
|
-
else
|
49
|
-
env['router.request'].params
|
50
|
-
end
|
51
|
-
# Provide access to the current controller to the request
|
52
|
-
# Now we can eval route, but because we have "throw halt" we need to be
|
53
|
-
# (en)sure to reset old layout and run controller after filters.
|
54
|
-
original_params = @params
|
55
|
-
parent_layout = @layout
|
56
|
-
successful = false
|
57
|
-
begin
|
58
|
-
filter! :before
|
59
|
-
(@route.before_filters - settings.filters[:before]).each { |block| instance_eval(&block) }
|
60
|
-
@layout = path.route.use_layout if path.route.use_layout
|
61
|
-
@route.custom_conditions.each { |block| pass if block.bind(self).call == false }
|
62
|
-
halt_response = catch(:halt) { route_eval { @route.dest[self, @block_params] } }
|
63
|
-
@_response_buffer = halt_response.is_a?(Array) ? halt_response.last : halt_response
|
64
|
-
successful = true
|
65
|
-
halt halt_response
|
66
|
-
ensure
|
67
|
-
(@route.after_filters - settings.filters[:after]).each { |block| instance_eval(&block) } if successful
|
68
|
-
@layout = parent_layout
|
69
|
-
@params = original_params
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Route
|
75
|
-
VALID_HTTP_VERBS.replace %w[GET POST PUT PATCH DELETE HEAD OPTIONS LINK UNLINK]
|
76
|
-
|
77
|
-
attr_accessor :use_layout, :controller, :action, :cache, :cache_key, :cache_expires, :parent
|
78
|
-
|
79
|
-
def before_filters(&block)
|
80
|
-
@_before_filters ||= []
|
81
|
-
@_before_filters << block if block_given?
|
82
|
-
|
83
|
-
@_before_filters
|
84
|
-
end
|
85
|
-
|
86
|
-
def after_filters(&block)
|
87
|
-
@_after_filters ||= []
|
88
|
-
@_after_filters << block if block_given?
|
89
|
-
|
90
|
-
@_after_filters
|
91
|
-
end
|
92
|
-
|
93
|
-
def custom_conditions(&block)
|
94
|
-
@_custom_conditions ||= []
|
95
|
-
@_custom_conditions << block if block_given?
|
96
|
-
|
97
|
-
@_custom_conditions
|
98
|
-
end
|
99
|
-
|
100
|
-
def significant_variable_names
|
101
|
-
@significant_variable_names ||= if @original_path.is_a?(String)
|
102
|
-
@original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
|
103
|
-
elsif @original_path.is_a?(Regexp) and @original_path.respond_to?(:named_captures)
|
104
|
-
@original_path.named_captures.keys.map(&:to_sym)
|
105
|
-
else
|
106
|
-
[]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def to(dest = nil, &dest_block)
|
111
|
-
@dest = dest || dest_block || raise("you didn't specify a destination")
|
112
|
-
|
113
|
-
@router.current_order ||= 0
|
114
|
-
@order = @router.current_order
|
115
|
-
@router.current_order += 1
|
116
|
-
|
117
|
-
if @dest.respond_to?(:url_mount=)
|
118
|
-
urlmount = UrlMount.new(@path_for_generation, @default_values || {}) # TODO url mount should accept nil here.
|
119
|
-
urlmount.url_mount = @router.url_mount if @router.url_mount
|
120
|
-
@dest.url_mount = urlmount
|
121
|
-
end
|
122
|
-
self
|
123
|
-
end
|
124
|
-
|
125
|
-
attr_accessor :order
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
attr_accessor :current_order
|
130
|
-
|
131
|
-
def sort!
|
132
|
-
@routes.sort!{ |a, b| a.order <=> b.order }
|
133
|
-
end
|
134
|
-
|
135
|
-
class Node::Glob
|
136
|
-
def to_code
|
137
|
-
id = root.next_counter
|
138
|
-
"request.params << (globbed_params#{id} = [])
|
139
|
-
until request.path.empty?
|
140
|
-
globbed_params#{id} << request.path.shift
|
141
|
-
#{super}
|
142
|
-
end
|
143
|
-
request.path[0,0] = globbed_params#{id}
|
144
|
-
request.params.pop"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
class Node::SpanningRegex
|
149
|
-
def to_code
|
150
|
-
params_count = @ordered_indicies.size
|
151
|
-
whole_path_var = "whole_path#{root.next_counter}"
|
152
|
-
"#{whole_path_var} = request.joined_path
|
153
|
-
if match = #{@matcher.inspect}.match(#{whole_path_var}) and match.begin(0).zero?
|
154
|
-
_#{whole_path_var} = request.path.dup
|
155
|
-
" << param_capturing_code << "
|
156
|
-
remaining_path = #{whole_path_var}[match[0].size + (#{whole_path_var}[match[0].size] == ?/ ? 1 : 0), #{whole_path_var}.size]
|
157
|
-
request.path = remaining_path.split('/')
|
158
|
-
#{node_to_code}
|
159
|
-
request.path = _#{whole_path_var}
|
160
|
-
request.params.slice!(#{-params_count}, #{params_count})
|
161
|
-
end
|
162
|
-
"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# Monkey patching the Request class. Using Rack::Utils.unescape rather than
|
167
|
-
# URI.unescape which can't handle utf-8 chars
|
168
|
-
class Request
|
169
|
-
def initialize(path, rack_request)
|
170
|
-
@rack_request = rack_request
|
171
|
-
@path = path.split(/\//).map{|part| Rack::Utils.unescape(part) }
|
172
|
-
@path.shift if @path.first == ''
|
173
|
-
@path.push('') if path[-1] == ?/
|
174
|
-
@extra_env = {}
|
175
|
-
@params = []
|
176
|
-
@acceptable_methods = Set.new
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
class Node::Path
|
181
|
-
def to_code
|
182
|
-
path_ivar = inject_root_ivar(self)
|
183
|
-
"#{"if !callback && request.path.size == 1 && request.path.first == '' && (request.rack_request.head? || request.rack_request.get?) && request.rack_request.path_info[-1] == ?/
|
184
|
-
catch(:pass) do
|
185
|
-
response = ::Rack::Response.new
|
186
|
-
response.redirect(request.rack_request.path_info[0, request.rack_request.path_info.size - 1], 302)
|
187
|
-
return response.finish
|
188
|
-
end
|
189
|
-
end" if router.redirect_trailing_slash?}
|
190
|
-
|
191
|
-
#{"if request.#{router.ignore_trailing_slash? ? 'path_finished?' : 'path.empty?'}" unless route.match_partially}
|
192
|
-
catch(:pass) do
|
193
|
-
if callback
|
194
|
-
request.called = true
|
195
|
-
callback.call(Response.new(request, #{path_ivar}))
|
196
|
-
else
|
197
|
-
env = request.rack_request.dup.env
|
198
|
-
env['router.request'] = request
|
199
|
-
env['router.params'] ||= {}
|
200
|
-
#{"env['router.params'].merge!(Hash[#{param_names.inspect}.zip(request.params)])" if dynamic?}
|
201
|
-
env['router.params'] = env['router.params'].with_indifferent_access
|
202
|
-
@router.rewrite#{"_partial" if route.match_partially}_path_info(env, request)
|
203
|
-
response = @router.process_destination_path(#{path_ivar}, env)
|
204
|
-
return response unless router.pass_on_response(response)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
#{"end" unless route.match_partially}"
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
2
|
+
require 'padrino-core/ext/sinatra'
|
3
|
+
require 'padrino-core/ext/http_router'
|
4
|
+
require 'padrino-core/filter'
|
211
5
|
|
212
6
|
module Padrino
|
213
|
-
class Filter
|
214
|
-
attr_reader :block
|
215
|
-
|
216
|
-
def initialize(mode, scoped_controller, options, args, &block)
|
217
|
-
@mode, @scoped_controller, @options, @args, @block = mode, scoped_controller, options, args, block
|
218
|
-
end
|
219
|
-
|
220
|
-
def apply?(request)
|
221
|
-
detect = match_with_arguments?(request) || match_with_options?(request)
|
222
|
-
detect ^ !@mode
|
223
|
-
end
|
224
|
-
|
225
|
-
def to_proc
|
226
|
-
if @args.empty? && @options.empty?
|
227
|
-
block
|
228
|
-
else
|
229
|
-
filter = self
|
230
|
-
proc { instance_eval(&filter.block) if filter.apply?(request) }
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
private
|
235
|
-
|
236
|
-
def scoped_controller_name
|
237
|
-
@scoped_controller_name ||= Array(@scoped_controller).join("_")
|
238
|
-
end
|
239
|
-
|
240
|
-
def match_with_arguments?(request)
|
241
|
-
route, path = request.route_obj, request.path_info
|
242
|
-
@args.any? do |argument|
|
243
|
-
if argument.instance_of?(Symbol)
|
244
|
-
next unless route
|
245
|
-
name = route.name
|
246
|
-
argument == name || name == [scoped_controller_name, argument].join(" ").to_sym
|
247
|
-
else
|
248
|
-
argument === path
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def match_with_options?(request)
|
254
|
-
user_agent = request.user_agent
|
255
|
-
@options.any?{|name, value| value === (name == :agent ? user_agent : request.send(name)) }
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
7
|
##
|
260
8
|
# Padrino provides advanced routing definition support to make routes and
|
261
9
|
# url generation much easier. This routing system supports named route
|
@@ -387,35 +135,7 @@ module Padrino
|
|
387
135
|
#
|
388
136
|
def controller(*args, &block)
|
389
137
|
if block_given?
|
390
|
-
|
391
|
-
|
392
|
-
# Controller defaults.
|
393
|
-
@_controller, original_controller = args, @_controller
|
394
|
-
@_parents, original_parent = options.delete(:parent), @_parents
|
395
|
-
@_provides, original_provides = options.delete(:provides), @_provides
|
396
|
-
@_use_format, original_use_format = options.delete(:use_format), @_use_format
|
397
|
-
@_cache, original_cache = options.delete(:cache), @_cache
|
398
|
-
@_map, original_map = options.delete(:map), @_map
|
399
|
-
@_conditions, original_conditions = options.delete(:conditions), @_conditions
|
400
|
-
@_defaults, original_defaults = options, @_defaults
|
401
|
-
@_accepts, original_accepts = options.delete(:accepts), @_accepts
|
402
|
-
@_params, original_params = options.delete(:params), @_params
|
403
|
-
|
404
|
-
# Application defaults.
|
405
|
-
@filters, original_filters = { :before => @filters[:before].dup, :after => @filters[:after].dup }, @filters
|
406
|
-
@layout, original_layout = nil, @layout
|
407
|
-
|
408
|
-
instance_eval(&block)
|
409
|
-
|
410
|
-
# Application defaults.
|
411
|
-
@filters = original_filters
|
412
|
-
@layout = original_layout
|
413
|
-
|
414
|
-
# Controller defaults.
|
415
|
-
@_controller, @_parents, @_cache = original_controller, original_parent, original_cache
|
416
|
-
@_defaults, @_provides, @_map = original_defaults, original_provides, original_map
|
417
|
-
@_conditions, @_use_format, @_accepts = original_conditions, original_use_format, original_accepts
|
418
|
-
@_params = original_params
|
138
|
+
with_new_options(*args) { instance_eval(&block) }
|
419
139
|
else
|
420
140
|
include(*args) if extensions.any?
|
421
141
|
end
|
@@ -489,10 +209,11 @@ module Padrino
|
|
489
209
|
# @see http://www.padrinorb.com/guides/controllers#route-filters
|
490
210
|
#
|
491
211
|
def construct_filter(*args, &block)
|
492
|
-
options = args.
|
493
|
-
except = options.
|
494
|
-
|
495
|
-
|
212
|
+
options = args.extract_options!
|
213
|
+
if except = options.delete(:except)
|
214
|
+
fail "You cannot use :except with other options specified" unless args.empty? && options.empty?
|
215
|
+
options = Array(except).extract_options!
|
216
|
+
end
|
496
217
|
Filter.new(!except, @_controller, options, Array(except || args), &block)
|
497
218
|
end
|
498
219
|
|
@@ -523,8 +244,8 @@ module Padrino
|
|
523
244
|
def parent(name, options={})
|
524
245
|
defaults = { :optional => false, :map => name.to_s }
|
525
246
|
options = defaults.merge(options)
|
526
|
-
@
|
527
|
-
@
|
247
|
+
@_parent = Array(@_parent) unless @_parent.is_a?(Array)
|
248
|
+
@_parent << Parent.new(name, options)
|
528
249
|
end
|
529
250
|
|
530
251
|
##
|
@@ -612,20 +333,9 @@ module Padrino
|
|
612
333
|
#
|
613
334
|
def url(*args)
|
614
335
|
params = args.extract_options!
|
615
|
-
names, params_array = args.partition{|a| a.is_a?(Symbol)}
|
616
|
-
name = names[0, 2].join(" ").to_sym # route name is concatenated with underscores
|
617
336
|
fragment = params.delete(:fragment) || params.delete(:anchor)
|
618
|
-
|
619
|
-
|
620
|
-
if params_array.empty?
|
621
|
-
compiled_router.path(name, params)
|
622
|
-
else
|
623
|
-
compiled_router.path(name, *(params_array << params))
|
624
|
-
end
|
625
|
-
rebase_url(fragment ? url + '#' + fragment : url)
|
626
|
-
rescue HttpRouter::InvalidRouteException
|
627
|
-
route_error = "route mapping for url(#{name.inspect}) could not be found!"
|
628
|
-
raise Padrino::Routing::UnrecognizedException.new(route_error)
|
337
|
+
path = make_path_with_params(args, value_to_param(params.symbolize_keys))
|
338
|
+
rebase_url(fragment ? path << '#' << fragment : path)
|
629
339
|
end
|
630
340
|
alias :url_for :url
|
631
341
|
|
@@ -637,6 +347,15 @@ module Padrino
|
|
637
347
|
route('HEAD', path, *args, &block)
|
638
348
|
end
|
639
349
|
|
350
|
+
def put(path, *args, &block) route 'PUT', path, *args, &block end
|
351
|
+
def post(path, *args, &block) route 'POST', path, *args, &block end
|
352
|
+
def delete(path, *args, &block) route 'DELETE', path, *args, &block end
|
353
|
+
def head(path, *args, &block) route 'HEAD', path, *args, &block end
|
354
|
+
def options(path, *args, &block) route 'OPTIONS', path, *args, &block end
|
355
|
+
def patch(path, *args, &block) route 'PATCH', path, *args, &block end
|
356
|
+
def link(path, *args, &block) route 'LINK', path, *args, &block end
|
357
|
+
def unlink(path, *args, &block) route 'UNLINK', path, *args, &block end
|
358
|
+
|
640
359
|
def rebase_url(url)
|
641
360
|
if url.start_with?('/')
|
642
361
|
new_url = ''
|
@@ -649,19 +368,56 @@ module Padrino
|
|
649
368
|
end
|
650
369
|
|
651
370
|
private
|
371
|
+
|
372
|
+
CONTROLLER_OPTIONS = [ :parent, :provides, :use_format, :cache, :expires, :map, :conditions, :accepts, :params ].freeze
|
373
|
+
|
374
|
+
# Saves controller options, yields the block, restores controller options.
|
375
|
+
def with_new_options(*args)
|
376
|
+
options = args.extract_options!
|
377
|
+
|
378
|
+
CONTROLLER_OPTIONS.each{ |key| replace_instance_variable("@_#{key}", options.delete(key)) }
|
379
|
+
replace_instance_variable(:@_controller, args)
|
380
|
+
replace_instance_variable(:@_defaults, options)
|
381
|
+
replace_instance_variable(:@filters, :before => @filters[:before].dup, :after => @filters[:after].dup)
|
382
|
+
replace_instance_variable(:@layout, nil)
|
383
|
+
|
384
|
+
yield
|
385
|
+
|
386
|
+
@original_instance.each do |key, value|
|
387
|
+
instance_variable_set(key, value)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
# Sets instance variable by name and saves the original value in @original_instance hash
|
392
|
+
def replace_instance_variable(name, value)
|
393
|
+
@original_instance ||= {}
|
394
|
+
@original_instance[name] = instance_variable_get(name)
|
395
|
+
instance_variable_set(name, value)
|
396
|
+
end
|
397
|
+
|
398
|
+
# Searches compiled router for a path responding to args and makes a path with params.
|
399
|
+
def make_path_with_params(args, params)
|
400
|
+
names, params_array = args.partition{ |arg| arg.is_a?(Symbol) }
|
401
|
+
name = names[0, 2].join(" ").to_sym
|
402
|
+
compiled_router.path(name, *(params_array << params))
|
403
|
+
rescue HttpRouter::InvalidRouteException
|
404
|
+
raise Padrino::Routing::UnrecognizedException, "Route mapping for url(#{name.inspect}) could not be found"
|
405
|
+
end
|
406
|
+
|
652
407
|
# Parse params from the url method
|
653
|
-
def value_to_param(
|
654
|
-
case
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
408
|
+
def value_to_param(object)
|
409
|
+
case object
|
410
|
+
when Array
|
411
|
+
object.map { |item| value_to_param(item) }.compact
|
412
|
+
when Hash
|
413
|
+
object.inject({}) do |all, (key, value)|
|
414
|
+
next all if value.nil?
|
415
|
+
all[key] = value_to_param(value)
|
416
|
+
all
|
417
|
+
end
|
418
|
+
when nil
|
419
|
+
else
|
420
|
+
object.respond_to?(:to_param) ? object.to_param : object
|
665
421
|
end
|
666
422
|
end
|
667
423
|
|
@@ -726,13 +482,14 @@ module Padrino
|
|
726
482
|
path, name, route_parents, options, route_options = *parse_route(path, route_options, verb)
|
727
483
|
options.reverse_merge!(@_conditions) if @_conditions
|
728
484
|
|
729
|
-
# Sinatra defaults
|
730
485
|
method_name = "#{verb} #{path}"
|
731
486
|
unbound_method = generate_method(method_name, &block)
|
732
487
|
|
733
|
-
block = block.arity
|
734
|
-
|
735
|
-
|
488
|
+
block = if block.arity == 0
|
489
|
+
proc{ |request, _| unbound_method.bind(request).call }
|
490
|
+
else
|
491
|
+
proc{ |request, block_params| unbound_method.bind(request).call(*block_params) }
|
492
|
+
end
|
736
493
|
|
737
494
|
invoke_hook(:route_added, verb, path, block)
|
738
495
|
|
@@ -743,6 +500,7 @@ module Padrino
|
|
743
500
|
priority_name = options.delete(:priority) || :normal
|
744
501
|
priority = ROUTE_PRIORITY[priority_name] or raise("Priority #{priority_name} not recognized, try #{ROUTE_PRIORITY.keys.join(', ')}")
|
745
502
|
route.cache = options.key?(:cache) ? options.delete(:cache) : @_cache
|
503
|
+
route.cache_expires = options.key?(:expires) ? options.delete(:expires) : @_expires
|
746
504
|
route.parent = route_parents ? (route_parents.count == 1 ? route_parents.first : route_parents) : route_parents
|
747
505
|
route.add_request_method(verb.downcase.to_sym)
|
748
506
|
route.host = options.delete(:host) if options.key?(:host)
|
@@ -759,7 +517,7 @@ module Padrino
|
|
759
517
|
end
|
760
518
|
|
761
519
|
# Add Sinatra conditions.
|
762
|
-
options.each
|
520
|
+
options.each{ |option, args| route.respond_to?(option) ? route.send(option, *args) : send(option, *args) }
|
763
521
|
conditions, @conditions = @conditions, []
|
764
522
|
route.custom_conditions.concat(conditions)
|
765
523
|
|
@@ -836,8 +594,8 @@ module Padrino
|
|
836
594
|
end
|
837
595
|
|
838
596
|
# Now we need to parse our 'parent' params and parent scope.
|
839
|
-
if !absolute_map and parent_params = options.delete(:parent) || @
|
840
|
-
parent_params = (Array(@
|
597
|
+
if !absolute_map and parent_params = options.delete(:parent) || @_parent
|
598
|
+
parent_params = (Array(@_parent) + Array(parent_params)).uniq
|
841
599
|
path = process_path_for_parent_params(path, parent_params)
|
842
600
|
end
|
843
601
|
|
@@ -873,7 +631,9 @@ module Padrino
|
|
873
631
|
# Used for calculating path in route method.
|
874
632
|
#
|
875
633
|
def process_path_for_with_params(path, with_params)
|
876
|
-
File.join(path, Array(with_params).map
|
634
|
+
File.join(path, Array(with_params).map do |step|
|
635
|
+
step.kind_of?(String) ? step : step.inspect
|
636
|
+
end.join("/"))
|
877
637
|
end
|
878
638
|
|
879
639
|
##
|
@@ -928,51 +688,29 @@ module Padrino
|
|
928
688
|
#
|
929
689
|
def provides(*types)
|
930
690
|
@_use_format = true
|
691
|
+
mime_types = types.map{ |type| mime_type(CONTENT_TYPE_ALIASES[type] || type) }
|
931
692
|
condition do
|
932
|
-
|
933
|
-
url_format = params[:format].to_sym if params[:format]
|
934
|
-
accepts = request.accept.map(&:to_str)
|
935
|
-
accepts.clear if accepts == ["*/*"]
|
693
|
+
return provides_format?(types, params[:format].to_sym) if params[:format]
|
936
694
|
|
695
|
+
accepts = request.accept.map(&:to_str)
|
937
696
|
# Per rfc2616-sec14:
|
938
697
|
# Assume */* if no ACCEPT header is given.
|
939
|
-
catch_all =
|
940
|
-
matching_types = accepts.empty? ? mime_types.slice(0,1) : (accepts & mime_types)
|
941
|
-
if matching_types.empty? && types.include?(:any)
|
942
|
-
matching_types = accepts
|
943
|
-
end
|
698
|
+
catch_all = accepts.delete("*/*")
|
944
699
|
|
945
|
-
|
946
|
-
type = ::Rack::Mime::MIME_TYPES.find { |k, v| v == matching_types.first }[0].sub(/\./,'').to_sym
|
947
|
-
accept_format = CONTENT_TYPE_ALIASES[type] || type
|
948
|
-
elsif catch_all && !types.include?(:any)
|
949
|
-
type = types.first
|
950
|
-
accept_format = CONTENT_TYPE_ALIASES[type] || type
|
951
|
-
end
|
700
|
+
return provides_any?(accepts) if types.include?(:any)
|
952
701
|
|
953
|
-
|
954
|
-
types.include?(accept_format) ||
|
955
|
-
types.include?(url_format) ||
|
956
|
-
((!url_format) && request.accept.empty? && types.include?(:html))
|
702
|
+
accepts = accepts.empty? ? mime_types.slice(0,1) : (accepts & mime_types)
|
957
703
|
|
958
|
-
|
959
|
-
|
960
|
-
# provided type.
|
961
|
-
halt 406 if
|
962
|
-
(!url_format && !accepts.empty? && !matched_format) ||
|
963
|
-
(settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept && url_format && !matched_format)
|
704
|
+
type = accepts.first && mime_symbol(accepts.first)
|
705
|
+
type ||= catch_all && types.first
|
964
706
|
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
content_type(@_content_type)
|
972
|
-
end
|
707
|
+
accept_format = CONTENT_TYPE_ALIASES[type] || type
|
708
|
+
if types.include?(accept_format)
|
709
|
+
content_type(accept_format || :html, :charset => 'utf-8')
|
710
|
+
else
|
711
|
+
halt 406 unless catch_all
|
712
|
+
false
|
973
713
|
end
|
974
|
-
|
975
|
-
matched_format
|
976
714
|
end
|
977
715
|
end
|
978
716
|
|
@@ -986,14 +724,10 @@ module Padrino
|
|
986
724
|
# # => GET /a CONTENT_TYPE application/xml => 406
|
987
725
|
#
|
988
726
|
def accepts(*types)
|
989
|
-
mime_types = types.map
|
727
|
+
mime_types = types.map{ |type| mime_type(CONTENT_TYPE_ALIASES[type] || type) }
|
990
728
|
condition do
|
991
|
-
halt 406 unless
|
992
|
-
|
993
|
-
content_type(media_type, :charset => 'utf-8')
|
994
|
-
else
|
995
|
-
content_type(media_type)
|
996
|
-
end
|
729
|
+
halt 406 unless mime_types.include?(request.media_type)
|
730
|
+
content_type(mime_symbol(request.media_type), :charset => 'utf-8')
|
997
731
|
end
|
998
732
|
end
|
999
733
|
|
@@ -1098,10 +832,10 @@ module Padrino
|
|
1098
832
|
# serving files from the public directory.
|
1099
833
|
#
|
1100
834
|
def static_file?(path_info)
|
1101
|
-
return
|
835
|
+
return unless public_dir = settings.public_folder
|
1102
836
|
public_dir = File.expand_path(public_dir)
|
1103
837
|
path = File.expand_path(public_dir + unescape(path_info))
|
1104
|
-
return
|
838
|
+
return unless path.start_with?(public_dir)
|
1105
839
|
return unless File.file?(path)
|
1106
840
|
return path
|
1107
841
|
end
|
@@ -1135,15 +869,35 @@ module Padrino
|
|
1135
869
|
# end
|
1136
870
|
#
|
1137
871
|
def content_type(type=nil, params={})
|
1138
|
-
unless type
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
@_content_type
|
872
|
+
return @_content_type unless type
|
873
|
+
params.delete(:charset) if type == :json
|
874
|
+
super(type, params)
|
875
|
+
@_content_type = type
|
1143
876
|
end
|
1144
877
|
|
1145
878
|
private
|
1146
879
|
|
880
|
+
def provides_any?(formats)
|
881
|
+
accepted_format = formats.first
|
882
|
+
type = accepted_format ? mime_symbol(accepted_format) : :html
|
883
|
+
content_type(CONTENT_TYPE_ALIASES[type] || type, :charset => 'utf-8')
|
884
|
+
end
|
885
|
+
|
886
|
+
def provides_format?(types, format)
|
887
|
+
if ([:any, format] & types).empty?
|
888
|
+
# Per rfc2616-sec14:
|
889
|
+
# Answer with 406 if accept is given but types to not match any provided type.
|
890
|
+
halt 406 if settings.respond_to?(:treat_format_as_accept) && settings.treat_format_as_accept
|
891
|
+
false
|
892
|
+
else
|
893
|
+
content_type(format || :html, :charset => 'utf-8')
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
def mime_symbol(media_type)
|
898
|
+
::Rack::Mime::MIME_TYPES.key(media_type).sub(/\./,'').to_sym
|
899
|
+
end
|
900
|
+
|
1147
901
|
def filter!(type, base=settings)
|
1148
902
|
base.filters[type].each { |block| instance_eval(&block) }
|
1149
903
|
end
|
@@ -1166,20 +920,19 @@ module Padrino
|
|
1166
920
|
|
1167
921
|
def route!(base=settings, pass_block=nil)
|
1168
922
|
Thread.current['padrino.instance'] = self
|
1169
|
-
|
1170
|
-
|
923
|
+
|
924
|
+
if base.compiled_router && result = base.compiled_router.call(@request.env)
|
925
|
+
if result.respond_to?(:each)
|
1171
926
|
route_eval do
|
1172
|
-
|
1173
|
-
status
|
1174
|
-
route_missing if
|
1175
|
-
route_missing if allow = response['Allow'] and allow.include?(request.env['REQUEST_METHOD'])
|
927
|
+
response.headers.merge!(result[1])
|
928
|
+
route_missing if status(result[0]) == 404
|
929
|
+
route_missing if (allow = response['Allow']) && allow.include?(request.env['REQUEST_METHOD'])
|
1176
930
|
end
|
1177
931
|
end
|
1178
932
|
else
|
1179
933
|
filter! :before
|
1180
934
|
end
|
1181
935
|
|
1182
|
-
# Run routes defined in superclass.
|
1183
936
|
if base.superclass.respond_to?(:router)
|
1184
937
|
route!(base.superclass, pass_block)
|
1185
938
|
return
|