padrino-core 0.12.2 → 0.12.3
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.
- 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
|