padrino-core 0.12.9 → 0.13.0.beta1
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 +5 -13
- data/bin/padrino +1 -2
- data/lib/padrino-core/application/application_setup.rb +10 -6
- data/lib/padrino-core/application/params_protection.rb +7 -1
- data/lib/padrino-core/application/routing.rb +88 -50
- data/lib/padrino-core/application/show_exceptions.rb +29 -0
- data/lib/padrino-core/application.rb +0 -19
- data/lib/padrino-core/caller.rb +1 -2
- data/lib/padrino-core/cli/base.rb +7 -11
- data/lib/padrino-core/cli/rake_tasks.rb +8 -21
- data/lib/padrino-core/loader.rb +13 -12
- data/lib/padrino-core/logger.rb +4 -32
- data/lib/padrino-core/mounter.rb +62 -21
- data/lib/padrino-core/path_router/compiler.rb +110 -0
- data/lib/padrino-core/path_router/error_handler.rb +8 -0
- data/lib/padrino-core/path_router/matcher.rb +123 -0
- data/lib/padrino-core/path_router/route.rb +169 -0
- data/lib/padrino-core/path_router.rb +119 -0
- data/lib/padrino-core/reloader/rack.rb +1 -4
- data/lib/padrino-core/reloader/storage.rb +3 -31
- data/lib/padrino-core/reloader.rb +12 -17
- data/lib/padrino-core/version.rb +1 -1
- data/lib/padrino-core.rb +0 -2
- data/padrino-core.gemspec +8 -2
- data/test/fixtures/apps/helpers/support.rb +1 -0
- data/test/fixtures/apps/{rack_apps.rb → mountable_apps/rack_apps.rb} +0 -4
- data/test/fixtures/apps/{static.html → mountable_apps/static.html} +0 -0
- data/test/fixtures/apps/precompiled_app.rb +19 -0
- data/test/fixtures/apps/system.rb +0 -2
- data/test/helper.rb +1 -1
- data/test/test_application.rb +18 -6
- data/test/test_csrf_protection.rb +6 -7
- data/test/test_filters.rb +18 -1
- data/test/test_logger.rb +1 -49
- data/test/test_mounter.rb +2 -4
- data/test/test_params_protection.rb +15 -15
- data/test/test_reloader_simple.rb +2 -2
- data/test/test_reloader_system.rb +0 -30
- data/test/test_restful_routing.rb +4 -4
- data/test/test_routing.rb +176 -54
- metadata +109 -49
- data/lib/padrino-core/cli/binstub.rb +0 -27
- data/lib/padrino-core/configuration.rb +0 -40
- data/lib/padrino-core/ext/http_router.rb +0 -201
- data/lib/padrino-core/mounter/application_extension.rb +0 -55
- data/test/fixtures/apps/custom_dependencies/custom_dependencies.rb +0 -11
- data/test/fixtures/apps/custom_dependencies/my_dependencies/my_dependency.rb +0 -0
- data/test/fixtures/apps/stealthy/app.rb +0 -7
- data/test/fixtures/apps/stealthy/helpers/stealthy_class_helpers.rb +0 -13
- data/test/test_configuration.rb +0 -29
- data/test/test_reloader_storage.rb +0 -51
data/lib/padrino-core/caller.rb
CHANGED
@@ -28,20 +28,16 @@ module Padrino
|
|
28
28
|
def console(*args)
|
29
29
|
prepare :console
|
30
30
|
require File.expand_path("../../version", __FILE__)
|
31
|
+
ARGV.clear
|
32
|
+
require 'irb'
|
33
|
+
begin
|
34
|
+
require "irb/completion"
|
35
|
+
rescue LoadError
|
36
|
+
end
|
31
37
|
require File.expand_path('config/boot.rb')
|
32
38
|
puts "=> Loading #{Padrino.env} console (Padrino v.#{Padrino.version})"
|
33
39
|
require File.expand_path('../console', __FILE__)
|
34
|
-
|
35
|
-
if defined? Pry
|
36
|
-
Pry.start
|
37
|
-
else
|
38
|
-
require 'irb'
|
39
|
-
begin
|
40
|
-
require "irb/completion"
|
41
|
-
rescue LoadError
|
42
|
-
end
|
43
|
-
IRB.start
|
44
|
-
end
|
40
|
+
IRB.start
|
45
41
|
end
|
46
42
|
|
47
43
|
desc "generate", "Executes the Padrino generator with given options (alternatively use 'gen' or 'g')."
|
@@ -1,3 +1,11 @@
|
|
1
|
+
Dir["{lib/tasks/**,tasks/**,test,spec}/*.rake"].each do |file|
|
2
|
+
begin
|
3
|
+
load(file)
|
4
|
+
rescue LoadError => e
|
5
|
+
warn "#{file}: #{e.message}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
1
9
|
# Loads the Padrino applications mounted within the project.
|
2
10
|
# Setting up the required environment for Padrino.
|
3
11
|
task :environment do
|
@@ -35,19 +43,6 @@ def list_app_routes(app, args)
|
|
35
43
|
end
|
36
44
|
end
|
37
45
|
|
38
|
-
def env_migration_version
|
39
|
-
version = ENV["MIGRATION_VERSION"]
|
40
|
-
if version.nil? && ENV["VERSION"]
|
41
|
-
deprecated = true
|
42
|
-
warn "Environment variable VERSION is deprecated, use MIGRATION_VERSION"
|
43
|
-
version = ENV["VERSION"]
|
44
|
-
end
|
45
|
-
version ? Integer(version) : nil
|
46
|
-
rescue ArgumentError
|
47
|
-
warn "Environment variable #{deprecated ? '' : 'MIGRATION_'}VERSION=#{version} should be non-existant or Integer"
|
48
|
-
nil
|
49
|
-
end
|
50
|
-
|
51
46
|
desc "Displays a listing of the named routes within a project, optionally only those matched by [query]"
|
52
47
|
task :routes, [:query] => :environment do |t, args|
|
53
48
|
Padrino.mounted_apps.each do |app|
|
@@ -62,11 +57,3 @@ namespace :routes do
|
|
62
57
|
list_app_routes(app, args) if app
|
63
58
|
end
|
64
59
|
end
|
65
|
-
|
66
|
-
Dir["{lib/tasks/**,tasks/**,test,spec}/*.rake"].each do |file|
|
67
|
-
begin
|
68
|
-
load(File.expand_path(file))
|
69
|
-
rescue LoadError => e
|
70
|
-
warn "#{file}: #{e.message}"
|
71
|
-
end
|
72
|
-
end
|
data/lib/padrino-core/loader.rb
CHANGED
@@ -58,9 +58,22 @@ module Padrino
|
|
58
58
|
require_dependencies(*dependency_paths)
|
59
59
|
after_load.each(&:call)
|
60
60
|
logger.devel "Loaded Padrino in #{Time.now - began_at} seconds"
|
61
|
+
precompile_all_routes!
|
61
62
|
Thread.current[:padrino_loaded] = true
|
62
63
|
end
|
63
64
|
|
65
|
+
##
|
66
|
+
# Precompiles all routes if :precompile_routes is set to true
|
67
|
+
#
|
68
|
+
def precompile_all_routes!
|
69
|
+
mounted_apps.each do |app|
|
70
|
+
app_obj = app.app_obj
|
71
|
+
next unless app_obj.respond_to?(:precompile_routes?) && app_obj.precompile_routes?
|
72
|
+
app_obj.setup_application!
|
73
|
+
logger.devel "Precompiled routes of #{app_obj} (routes size #{app_obj.compiled_router.routes.size})"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
64
77
|
##
|
65
78
|
# Clear the padrino env.
|
66
79
|
#
|
@@ -170,18 +183,6 @@ module Padrino
|
|
170
183
|
@_dependency_paths ||= default_dependency_paths + modules_dependency_paths
|
171
184
|
end
|
172
185
|
|
173
|
-
# Deprecated
|
174
|
-
def set_load_paths(*)
|
175
|
-
warn 'Padrino.set_load_paths is deprecated. Please, use $LOAD_PATH.concat(paths)'
|
176
|
-
[]
|
177
|
-
end
|
178
|
-
|
179
|
-
# Deprecated
|
180
|
-
def load_paths
|
181
|
-
warn 'Padrino.load_paths is deprecated. Please, use Padrino::Application#prerequisites'
|
182
|
-
[]
|
183
|
-
end
|
184
|
-
|
185
186
|
private
|
186
187
|
|
187
188
|
def modules_dependency_paths
|
data/lib/padrino-core/logger.rb
CHANGED
@@ -73,7 +73,7 @@ module Padrino
|
|
73
73
|
bench(args[0], args[1], args[2], name)
|
74
74
|
else
|
75
75
|
if location = resolve_source_location(caller(1).shift)
|
76
|
-
args.
|
76
|
+
args.prepend(location)
|
77
77
|
end if enable_source_location?
|
78
78
|
push(args * '', name)
|
79
79
|
end
|
@@ -264,9 +264,6 @@ module Padrino
|
|
264
264
|
#
|
265
265
|
# :log_level:: Once of [:fatal, :error, :warn, :info, :debug]
|
266
266
|
# :stream:: Once of [:to_file, :null, :stdout, :stderr] our your custom stream
|
267
|
-
# :log_path:: Defines log file path or directory if :stream is :to_file
|
268
|
-
# If it's a file, its location is created by mkdir_p.
|
269
|
-
# If it's a directory, it must exist. In this case log name is '<env>.log'
|
270
267
|
# :log_level::
|
271
268
|
# The log level from, e.g. :fatal or :info. Defaults to :warn in the
|
272
269
|
# production environment and :debug otherwise.
|
@@ -282,10 +279,6 @@ module Padrino
|
|
282
279
|
# Padrino::Logger::Config[:development] = { :log_level => :debug, :stream => :to_file }
|
283
280
|
# # or you can edit our defaults
|
284
281
|
# Padrino::Logger::Config[:development][:log_level] = :error
|
285
|
-
# # or change log file path
|
286
|
-
# Padrino::Logger::Config[:development][:log_path] = 'logs/app-development.txt'
|
287
|
-
# # or change log file directory
|
288
|
-
# Padrino::Logger::Config[:development][:log_path] = '/var/logs/padrino'
|
289
282
|
# # or you can use your stream
|
290
283
|
# Padrino::Logger::Config[:development][:stream] = StringIO.new
|
291
284
|
#
|
@@ -336,18 +329,8 @@ module Padrino
|
|
336
329
|
|
337
330
|
stream = case config[:stream]
|
338
331
|
when :to_file
|
339
|
-
|
340
|
-
|
341
|
-
if File.directory?(filename)
|
342
|
-
filename = File.join(filename, "#{Padrino.env}.log")
|
343
|
-
else
|
344
|
-
FileUtils.mkdir_p(File.dirname(filename))
|
345
|
-
end
|
346
|
-
File.new(filename, 'a+')
|
347
|
-
else
|
348
|
-
FileUtils.mkdir_p(Padrino.root('log')) unless File.exist?(Padrino.root('log'))
|
349
|
-
File.new(Padrino.root('log', "#{Padrino.env}.log"), 'a+')
|
350
|
-
end
|
332
|
+
FileUtils.mkdir_p(Padrino.root('log')) unless File.exist?(Padrino.root('log'))
|
333
|
+
File.new(Padrino.root('log', "#{Padrino.env}.log"), 'a+')
|
351
334
|
when :null then StringIO.new
|
352
335
|
when :stdout then $stdout
|
353
336
|
when :stderr then $stderr
|
@@ -385,12 +368,6 @@ module Padrino
|
|
385
368
|
# @option options [Symbol] :colorize_logging (true)
|
386
369
|
# Whether or not to colorize log messages. Defaults to: true.
|
387
370
|
#
|
388
|
-
# @option options [Symbol] :sanitize_encoding (false)
|
389
|
-
# Logger will replace undefined or broken characters with
|
390
|
-
# “uFFFD” for Unicode and “?” otherwise.
|
391
|
-
# Can be an encoding, false or true.
|
392
|
-
# If it's true, logger sanitizes to Encoding.default_external.
|
393
|
-
#
|
394
371
|
def initialize(options={})
|
395
372
|
@buffer = []
|
396
373
|
@auto_flush = options.has_key?(:auto_flush) ? options[:auto_flush] : true
|
@@ -402,8 +379,6 @@ module Padrino
|
|
402
379
|
@log_static = options.has_key?(:log_static) ? options[:log_static] : false
|
403
380
|
@colorize_logging = options.has_key?(:colorize_logging) ? options[:colorize_logging] : true
|
404
381
|
@source_location = options[:source_location]
|
405
|
-
@sanitize_encoding = options[:sanitize_encoding] || false
|
406
|
-
@sanitize_encoding = Encoding.default_external if @sanitize_encoding == true
|
407
382
|
colorize! if @colorize_logging
|
408
383
|
end
|
409
384
|
|
@@ -417,10 +392,7 @@ module Padrino
|
|
417
392
|
def flush
|
418
393
|
return unless @buffer.size > 0
|
419
394
|
@@mutex.synchronize do
|
420
|
-
@buffer.
|
421
|
-
line.encode!(@sanitize_encoding, :invalid => :replace, :undef => :replace) if @sanitize_encoding
|
422
|
-
@log.write(line)
|
423
|
-
end
|
395
|
+
@log.write(@buffer.join(''))
|
424
396
|
@buffer.clear
|
425
397
|
end
|
426
398
|
end
|
data/lib/padrino-core/mounter.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'delegate'
|
2
2
|
|
3
3
|
module Padrino
|
4
4
|
##
|
@@ -14,6 +14,55 @@ module Padrino
|
|
14
14
|
class MounterException < RuntimeError
|
15
15
|
end
|
16
16
|
|
17
|
+
class ApplicationWrapper < SimpleDelegator
|
18
|
+
attr_accessor :uri_root
|
19
|
+
attr_writer :public_folder
|
20
|
+
|
21
|
+
def initialize(app, options = {})
|
22
|
+
@options = options
|
23
|
+
super(app)
|
24
|
+
end
|
25
|
+
|
26
|
+
def dependencies
|
27
|
+
@__dependencies ||= Dir["#{root}/**/*.rb"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def prerequisites
|
31
|
+
@__prerequisites ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
def app_file
|
35
|
+
return @__app_file if @__app_file
|
36
|
+
obj = __getobj__
|
37
|
+
@__app_file = obj.respond_to?(:app_file) ? obj.app_file : @options[:app_file]
|
38
|
+
end
|
39
|
+
|
40
|
+
def root
|
41
|
+
return @__root if @__root
|
42
|
+
obj = __getobj__
|
43
|
+
@__root = obj.respond_to?(:root) ? obj.root : File.expand_path("#{app_file}/../")
|
44
|
+
end
|
45
|
+
|
46
|
+
def public_folder
|
47
|
+
return @public_folder if @public_folder
|
48
|
+
obj = __getobj__
|
49
|
+
@public_folder = obj.respond_to?(:public_folder) ? obj.public_folder : ""
|
50
|
+
end
|
51
|
+
|
52
|
+
def app_name
|
53
|
+
@__app_name ||= @options[:app_name] || __getobj__.to_s.underscore.to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
def setup_application!
|
57
|
+
@configured ||=
|
58
|
+
begin
|
59
|
+
$LOAD_PATH.concat(prerequisites)
|
60
|
+
Padrino.require_dependencies(dependencies, :force => true) if root.start_with?(Padrino.root)
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
17
66
|
attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host, :cascade
|
18
67
|
|
19
68
|
##
|
@@ -34,10 +83,7 @@ module Padrino
|
|
34
83
|
@app_file = options[:app_file] || locate_app_file
|
35
84
|
@app_obj = options[:app_obj] || app_constant || locate_app_object
|
36
85
|
ensure_app_file! || ensure_app_object!
|
37
|
-
unless padrino_application?
|
38
|
-
@app_obj.extend ApplicationExtension
|
39
|
-
@app_obj.mounter_options = options
|
40
|
-
end
|
86
|
+
@app_obj = ApplicationWrapper.new(@app_obj, options) unless padrino_application?
|
41
87
|
@app_root = options[:app_root] || (@app_obj.respond_to?(:root) && @app_obj.root || File.dirname(@app_file))
|
42
88
|
@uri_root = "/"
|
43
89
|
@cascade = options[:cascade] ? true == options[:cascade] ? DEFAULT_CASCADE.dup : Array(options[:cascade]) : []
|
@@ -96,23 +142,20 @@ module Padrino
|
|
96
142
|
def map_onto(router)
|
97
143
|
app_data = self
|
98
144
|
app_obj = @app_obj
|
99
|
-
|
100
|
-
uri_root = app_data.uri_root
|
101
|
-
public_folder_exists = File.exist?(app_obj.public_folder)
|
102
|
-
|
103
145
|
if padrino_application?
|
104
|
-
app_obj.set :uri_root, uri_root
|
105
|
-
app_obj.set :app_name, app_obj.app_name.to_s
|
106
|
-
app_obj.set :
|
107
|
-
app_obj.set :
|
108
|
-
app_obj.set :
|
146
|
+
app_obj.set :uri_root, app_data.uri_root
|
147
|
+
app_obj.set :app_name, app_data.app_obj.app_name.to_s
|
148
|
+
app_obj.set :app_file, app_data.app_file unless File.exist?(app_obj.app_file)
|
149
|
+
app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
|
150
|
+
app_obj.set :public_folder, Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
|
151
|
+
app_obj.set :static, File.exist?(app_obj.public_folder) if app_obj.nil?
|
109
152
|
app_obj.set :cascade, app_data.cascade
|
110
153
|
else
|
111
|
-
app_obj.uri_root = uri_root
|
112
|
-
app_obj.public_folder = Padrino.root('public', uri_root) unless
|
154
|
+
app_obj.uri_root = app_data.uri_root
|
155
|
+
app_obj.public_folder = Padrino.root('public', app_data.uri_root) unless File.exist?(app_obj.public_folder)
|
113
156
|
end
|
114
157
|
app_obj.setup_application! # Initializes the app here with above settings.
|
115
|
-
router.map(:to => app_obj, :path => uri_root, :host => app_data.app_host)
|
158
|
+
router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
|
116
159
|
end
|
117
160
|
|
118
161
|
###
|
@@ -131,7 +174,7 @@ module Padrino
|
|
131
174
|
def named_routes
|
132
175
|
app_obj.routes.map { |route|
|
133
176
|
route_name = route.name.to_s
|
134
|
-
route_name =
|
177
|
+
route_name =
|
135
178
|
if route.controller
|
136
179
|
route_name.split(" ", 2).map{|name| ":#{name}" }.join(", ")
|
137
180
|
else
|
@@ -188,10 +231,8 @@ module Padrino
|
|
188
231
|
# Returns the determined location of the mounted application main file.
|
189
232
|
#
|
190
233
|
def locate_app_file
|
191
|
-
app_const = app_constant
|
192
|
-
|
193
234
|
candidates = []
|
194
|
-
candidates <<
|
235
|
+
candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
|
195
236
|
candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
|
196
237
|
candidates << Padrino.mounted_root(name.downcase, "app.rb")
|
197
238
|
simple_name = name.split("::").last.downcase
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Padrino
|
2
|
+
module PathRouter
|
3
|
+
#
|
4
|
+
# High performance engine for finding all routes which are matched with pattern
|
5
|
+
#
|
6
|
+
class Compiler
|
7
|
+
# All regexps generated by recursive compiler
|
8
|
+
attr_reader :regexps
|
9
|
+
|
10
|
+
##
|
11
|
+
# Constructs an instance of Padrino::PathRouter::Compiler
|
12
|
+
#
|
13
|
+
def initialize(routes)
|
14
|
+
@routes = routes
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Compiles all routes into regexps.
|
19
|
+
#
|
20
|
+
def compile!
|
21
|
+
return if compiled?
|
22
|
+
@regexps = @routes.map.with_index do |route, index|
|
23
|
+
route.index = index
|
24
|
+
/(?<_#{index}>#{route.matcher.to_regexp})/
|
25
|
+
end
|
26
|
+
@regexps = recursive_compile(@regexps)
|
27
|
+
@compiled = true
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Returns true if all routes has been compiled.
|
32
|
+
#
|
33
|
+
def compiled?
|
34
|
+
!!@compiled
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Finds routes by using request or env.
|
39
|
+
#
|
40
|
+
def find_by(request_or_env)
|
41
|
+
request = request_or_env.is_a?(Hash) ? Sinatra::Request.new(request_or_env) : request_or_env
|
42
|
+
pattern = encode_default_external(request.path_info)
|
43
|
+
verb = request.request_method
|
44
|
+
rotation { |offset| match?(offset, pattern) }.select { |route| route.verb == verb }
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Calls routes by using request.
|
49
|
+
#
|
50
|
+
def call_by_request(request)
|
51
|
+
rotation do |offset|
|
52
|
+
pattern = encode_default_external(request.path_info)
|
53
|
+
if route = match?(offset, pattern)
|
54
|
+
params = route.params_for(pattern, request.params)
|
55
|
+
yield(route, params) if route.verb == request.request_method
|
56
|
+
route
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Finds routes by using PATH_INFO.
|
63
|
+
#
|
64
|
+
def find_by_pattern(pattern)
|
65
|
+
pattern = pattern.encode(Encoding.default_external)
|
66
|
+
rotation { |offset| match?(offset, pattern) }
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
##
|
72
|
+
# Returns a instance of PathRouter::Route if path is matched with current regexp
|
73
|
+
#
|
74
|
+
def match?(offset, path)
|
75
|
+
current_regexp = @regexps[offset]
|
76
|
+
return unless current_regexp === path || current_regexp === path[0..-2]
|
77
|
+
@routes[offset..-1].detect{ |route| Regexp.last_match["_#{route.index}"] }
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Runs through all regexps to find routes.
|
82
|
+
#
|
83
|
+
def rotation(offset = 0)
|
84
|
+
compile! unless compiled?
|
85
|
+
loop.with_object([]) do |_, candidacies|
|
86
|
+
return candidacies unless route = yield(offset)
|
87
|
+
candidacies << route
|
88
|
+
offset = route.index.next
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Compiles routes into regexp recursively.
|
94
|
+
#
|
95
|
+
def recursive_compile(regexps, paths = [])
|
96
|
+
return paths if regexps.length.zero?
|
97
|
+
paths << Regexp.union(regexps)
|
98
|
+
regexps.shift
|
99
|
+
recursive_compile(regexps, paths)
|
100
|
+
end
|
101
|
+
|
102
|
+
##
|
103
|
+
# Encode string with Encoding.default_external
|
104
|
+
#
|
105
|
+
def encode_default_external(string)
|
106
|
+
string.encode(Encoding.default_external)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|