padrino-core 0.12.9 → 0.13.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|