pakyow-core 0.8rc1 → 0.8.rc4
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 +7 -0
- data/pakyow-core/lib/core/app.rb +448 -0
- data/pakyow-core/lib/core/base.rb +35 -12
- data/pakyow-core/lib/core/{configuration → config}/app.rb +38 -35
- data/pakyow-core/lib/core/config/base.rb +30 -0
- data/pakyow-core/lib/core/config/cookies.rb +21 -0
- data/pakyow-core/lib/core/config/logger.rb +37 -0
- data/pakyow-core/lib/core/{configuration → config}/server.rb +3 -1
- data/pakyow-core/lib/core/exceptions.rb +3 -0
- data/pakyow-core/lib/core/helpers.rb +20 -16
- data/pakyow-core/lib/core/loader.rb +1 -1
- data/pakyow-core/lib/core/middleware/logger.rb +170 -16
- data/pakyow-core/lib/core/middleware/static.rb +20 -8
- data/pakyow-core/lib/core/multilog.rb +19 -0
- data/pakyow-core/lib/core/request.rb +52 -30
- data/pakyow-core/lib/core/route_eval.rb +390 -0
- data/pakyow-core/lib/core/route_lookup.rb +17 -5
- data/pakyow-core/lib/core/route_set.rb +17 -210
- data/pakyow-core/lib/core/route_template_defaults.rb +18 -12
- data/pakyow-core/lib/core/router.rb +41 -31
- data/pakyow-core/lib/utils/dir.rb +19 -0
- data/pakyow-core/lib/utils/hash.rb +14 -4
- data/pakyow-core/lib/views/errors/404.html +77 -0
- data/pakyow-core/lib/views/errors/500.html +56 -0
- metadata +30 -53
- data/pakyow-core/bin/pakyow +0 -18
- data/pakyow-core/lib/commands/USAGE +0 -9
- data/pakyow-core/lib/commands/USAGE-CONSOLE +0 -12
- data/pakyow-core/lib/commands/USAGE-NEW +0 -11
- data/pakyow-core/lib/commands/USAGE-SERVER +0 -12
- data/pakyow-core/lib/commands/console.rb +0 -18
- data/pakyow-core/lib/commands/server.rb +0 -8
- data/pakyow-core/lib/core/application.rb +0 -330
- data/pakyow-core/lib/core/cache.rb +0 -25
- data/pakyow-core/lib/core/configuration/base.rb +0 -31
- data/pakyow-core/lib/core/fn_context.rb +0 -5
- data/pakyow-core/lib/core/log.rb +0 -39
- data/pakyow-core/lib/core/middleware/not_found.rb +0 -40
- data/pakyow-core/lib/core/middleware/presenter.rb +0 -25
- data/pakyow-core/lib/core/middleware/router.rb +0 -33
- data/pakyow-core/lib/core/middleware/setup.rb +0 -15
- data/pakyow-core/lib/core/presenter_base.rb +0 -11
- data/pakyow-core/lib/core/route_template.rb +0 -77
- data/pakyow-core/lib/generators/pakyow/app/app_generator.rb +0 -36
- data/pakyow-core/lib/generators/pakyow/app/templates/README +0 -54
- data/pakyow-core/lib/generators/pakyow/app/templates/app.rb +0 -12
- data/pakyow-core/lib/generators/pakyow/app/templates/config.ru +0 -3
- data/pakyow-core/lib/generators/pakyow/app/templates/public/favicon.ico +0 -0
- data/pakyow-core/lib/generators/pakyow/app/templates/rakefile +0 -2
- data/pakyow-core/lib/generators/pakyow/app/templates/views/main.html +0 -1
- data/pakyow-core/lib/generators/pakyow/app/templates/views/pakyow.html +0 -12
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pakyow
|
2
|
+
module Config
|
3
|
+
class Logger
|
4
|
+
Config::Base.register_config(:logger, self)
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :path, :name, :sync, :colorize, :auto_flush, :level
|
8
|
+
|
9
|
+
# Path to logs
|
10
|
+
def path
|
11
|
+
@path || "#{Config::Base.app.root}/logs"
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
@name || "requests.log"
|
16
|
+
end
|
17
|
+
|
18
|
+
def sync
|
19
|
+
instance_variable_defined?(:@sync) ? @sync : true
|
20
|
+
end
|
21
|
+
|
22
|
+
def auto_flush
|
23
|
+
instance_variable_defined?(:@auto_flush) ? @auto_flush : true
|
24
|
+
end
|
25
|
+
|
26
|
+
def colorize
|
27
|
+
instance_variable_defined?(:@colorize) ? @colorize : true
|
28
|
+
end
|
29
|
+
|
30
|
+
def level
|
31
|
+
@level || Pakyow::Logger::LEVELS[:debug]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,19 +1,25 @@
|
|
1
1
|
module Pakyow
|
2
2
|
|
3
|
-
#
|
4
|
-
module
|
5
|
-
def
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
def response
|
10
|
-
Pakyow.app.response
|
3
|
+
# For methods that should be accessible anywhere
|
4
|
+
module Helpers
|
5
|
+
def logger
|
6
|
+
request.logger
|
11
7
|
end
|
12
|
-
|
8
|
+
|
13
9
|
def router
|
14
10
|
RouteLookup.new
|
15
11
|
end
|
16
12
|
|
13
|
+
def request
|
14
|
+
@request
|
15
|
+
end
|
16
|
+
alias_method :req, :request
|
17
|
+
|
18
|
+
def response
|
19
|
+
@response
|
20
|
+
end
|
21
|
+
alias_method :res, :response
|
22
|
+
|
17
23
|
def params
|
18
24
|
request.params
|
19
25
|
end
|
@@ -25,14 +31,12 @@ module Pakyow
|
|
25
31
|
def cookies
|
26
32
|
request.cookies
|
27
33
|
end
|
28
|
-
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
include GeneralHelpers
|
33
|
-
|
34
|
-
def app
|
35
|
-
Pakyow.app
|
35
|
+
def config
|
36
|
+
Pakyow::Config::Base
|
36
37
|
end
|
37
38
|
end
|
39
|
+
|
40
|
+
# For methods that should only be accessible through App
|
41
|
+
module AppHelpers; end
|
38
42
|
end
|
@@ -17,7 +17,7 @@ module Pakyow
|
|
17
17
|
next if FileTest.directory?(path)
|
18
18
|
next if path.split('.')[-1] != 'rb'
|
19
19
|
|
20
|
-
if
|
20
|
+
if Config::Base.app.auto_reload
|
21
21
|
if !@times[path] || (@times[path] && File.mtime(path) - @times[path] > 0)
|
22
22
|
load(path)
|
23
23
|
@times[path] = File.mtime(path)
|
@@ -1,28 +1,124 @@
|
|
1
|
+
module Pakyow
|
2
|
+
class Logger
|
3
|
+
LEVELS = {
|
4
|
+
:debug => 0,
|
5
|
+
:info => 1,
|
6
|
+
:warn => 2,
|
7
|
+
:error => 3,
|
8
|
+
:fatal => 4,
|
9
|
+
:unknown => 5,
|
10
|
+
}
|
11
|
+
|
12
|
+
LEVEL_COLORS = {
|
13
|
+
:debug => :cyan,
|
14
|
+
:info => :green,
|
15
|
+
:warn => :yellow,
|
16
|
+
:error => :red,
|
17
|
+
:fatal => :red,
|
18
|
+
# :unknown => nil,
|
19
|
+
}
|
20
|
+
|
21
|
+
COLOR_TABLE = [
|
22
|
+
:black,
|
23
|
+
:red,
|
24
|
+
:green,
|
25
|
+
:yellow,
|
26
|
+
:blue,
|
27
|
+
:magenta,
|
28
|
+
:cyan,
|
29
|
+
:white,
|
30
|
+
]
|
31
|
+
|
32
|
+
RESET_SEQ = "\033[0m"
|
33
|
+
COLOR_SEQ = "\033[%dm"
|
34
|
+
BOLD_SEQ = "\033[1m"
|
35
|
+
|
36
|
+
def initialize(log = $stdout, level = 0, format = false, auto_flush = false)
|
37
|
+
@log, @level, @format, @auto_flush = log, level, format, auto_flush
|
38
|
+
@mutex = Mutex.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def <<(msg = nil, severity = :unknown)
|
42
|
+
msg << "\n"
|
43
|
+
|
44
|
+
msg = format(msg, severity) if @format
|
45
|
+
@mutex.synchronize do
|
46
|
+
@log.write msg
|
47
|
+
@log.flush if @auto_flush
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
alias :write :<<
|
52
|
+
|
53
|
+
def add(severity, msg = nil)
|
54
|
+
severity ||= LEVELS[:unknown]
|
55
|
+
return if severity < @level
|
56
|
+
|
57
|
+
write(msg, severity)
|
58
|
+
end
|
59
|
+
|
60
|
+
alias :log :add
|
61
|
+
|
62
|
+
def debug(msg = nil)
|
63
|
+
add(LEVELS[:debug], msg)
|
64
|
+
end
|
65
|
+
|
66
|
+
def info(msg = nil)
|
67
|
+
add(LEVELS[:info], msg)
|
68
|
+
end
|
69
|
+
|
70
|
+
def warn(msg = nil)
|
71
|
+
add(LEVELS[:warn], msg)
|
72
|
+
end
|
73
|
+
|
74
|
+
def error(msg = nil)
|
75
|
+
add(LEVELS[:error], msg)
|
76
|
+
end
|
77
|
+
|
78
|
+
def fatal(msg = nil)
|
79
|
+
add(LEVELS[:fatal], msg)
|
80
|
+
end
|
81
|
+
|
82
|
+
def format(msg, level)
|
83
|
+
return msg unless color = level_color(level)
|
84
|
+
return COLOR_SEQ % (30 + COLOR_TABLE.index(color)) + msg + RESET_SEQ
|
85
|
+
end
|
86
|
+
|
87
|
+
def level_color(level)
|
88
|
+
LEVEL_COLORS[LEVELS.key(level)]
|
89
|
+
end
|
90
|
+
|
91
|
+
def close
|
92
|
+
@log.close
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
1
98
|
module Pakyow
|
2
99
|
module Middleware
|
3
100
|
class Logger
|
101
|
+
# handles logging after an error occurs
|
102
|
+
Pakyow::App.after(:error) {
|
103
|
+
error = request.error
|
104
|
+
Pakyow.logger.error "[500] #{error}\n" + error.backtrace.join("\n") + "\n\n"
|
105
|
+
}
|
106
|
+
|
4
107
|
def initialize(app)
|
5
108
|
@app = app
|
6
109
|
end
|
7
|
-
|
110
|
+
|
8
111
|
def call(env)
|
112
|
+
env['rack.logger'] = Pakyow.logger
|
113
|
+
|
9
114
|
result = nil
|
10
115
|
difference = time { |began_at|
|
11
|
-
|
12
|
-
|
13
|
-
if error = catch(:error) {
|
14
|
-
result = @app.call(env)
|
15
|
-
nil
|
16
|
-
}
|
17
|
-
Log.enter "[500] #{error}\n"
|
18
|
-
Log.enter error.backtrace.join("\n") + "\n\n"
|
19
|
-
|
20
|
-
result = Pakyow.app.response.finish
|
21
|
-
end
|
116
|
+
Pakyow.logger << "#{env['REQUEST_METHOD']} #{env['REQUEST_URI']} for #{env['REMOTE_ADDR']} at #{began_at}"
|
117
|
+
result = @app.call(env)
|
22
118
|
}
|
23
|
-
|
24
|
-
|
25
|
-
|
119
|
+
|
120
|
+
status = result[0]
|
121
|
+
Pakyow.logger << "#{status} (#{nice_status(status)}) in #{difference}ms\n"
|
26
122
|
|
27
123
|
result
|
28
124
|
end
|
@@ -30,7 +126,65 @@ module Pakyow
|
|
30
126
|
def time
|
31
127
|
s = Time.now
|
32
128
|
yield(s)
|
33
|
-
(Time.now.to_f - s.to_f) * 1000.0
|
129
|
+
time = ((Time.now.to_f - s.to_f) * 1000.0)
|
130
|
+
(time * 10**2).round / (10**2).to_f
|
131
|
+
end
|
132
|
+
|
133
|
+
def nice_status(status)
|
134
|
+
{
|
135
|
+
100 => 'Continue',
|
136
|
+
101 => 'Switching Protocols',
|
137
|
+
|
138
|
+
200 => 'OK',
|
139
|
+
201 => 'Created',
|
140
|
+
202 => 'Accepted',
|
141
|
+
203 => 'Non-Authoritative Information',
|
142
|
+
204 => 'No Content',
|
143
|
+
205 => 'Reset Content',
|
144
|
+
206 => 'Partial Content',
|
145
|
+
|
146
|
+
300 => 'Multiple Choices',
|
147
|
+
301 => 'Moved Permanently',
|
148
|
+
302 => 'Found',
|
149
|
+
303 => 'See Other',
|
150
|
+
304 => 'Not Modified',
|
151
|
+
305 => 'Use Proxy',
|
152
|
+
306 => 'Switch Proxy',
|
153
|
+
307 => 'Temporary Redirect',
|
154
|
+
|
155
|
+
400 => 'Bad Request',
|
156
|
+
401 => 'Unauthorized',
|
157
|
+
402 => 'Payment Required',
|
158
|
+
403 => 'Forbidden',
|
159
|
+
404 => 'Not Found',
|
160
|
+
405 => 'Method Not Allowed',
|
161
|
+
406 => 'Not Acceptable',
|
162
|
+
407 => 'Proxy Authentication Required',
|
163
|
+
408 => 'Request Timeout',
|
164
|
+
409 => 'Conflict',
|
165
|
+
410 => 'Gone',
|
166
|
+
411 => 'Length Required',
|
167
|
+
412 => 'Precondition Failed',
|
168
|
+
413 => 'Request Entity Too Large',
|
169
|
+
414 => 'Request-URI Too Long',
|
170
|
+
415 => 'Unsupported Media Type',
|
171
|
+
416 => 'Requested Range Not Satisfiable',
|
172
|
+
417 => 'Expectation Failed',
|
173
|
+
418 => 'I\'m a teapot',
|
174
|
+
|
175
|
+
500 => 'Internal Server Error',
|
176
|
+
501 => 'Not Implemented',
|
177
|
+
502 => 'Bad Gateway',
|
178
|
+
503 => 'Service Unavailable',
|
179
|
+
504 => 'Gateway Timeout',
|
180
|
+
505 => 'HTTP Version Not Supported',
|
181
|
+
506 => 'Variant Also Negotiates',
|
182
|
+
507 => 'Insufficient Storage',
|
183
|
+
508 => 'Loop Detected',
|
184
|
+
509 => 'Bandwidth Limit Exceeded',
|
185
|
+
510 => 'Not Extended',
|
186
|
+
511 => 'Network Authentication Required'
|
187
|
+
}[status] || '?'
|
34
188
|
end
|
35
189
|
end
|
36
190
|
end
|
@@ -4,24 +4,36 @@ module Pakyow
|
|
4
4
|
def initialize(app)
|
5
5
|
@app = app
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def call(env)
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
static, resource_path = is_static?(env)
|
10
|
+
|
11
|
+
if static
|
12
12
|
catch(:halt) do
|
13
|
-
Pakyow.app.
|
13
|
+
app = Pakyow.app.dup
|
14
|
+
app.response = Response.new
|
15
|
+
app.request = Request.new(env)
|
16
|
+
app.send(File.open(resource_path))
|
14
17
|
end
|
15
18
|
else
|
16
19
|
@app.call(env)
|
17
20
|
end
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
private
|
21
|
-
|
24
|
+
|
22
25
|
def is_static?(env)
|
23
|
-
env['PATH_INFO'] =~ /\.(.*)$/
|
26
|
+
return false unless env['PATH_INFO'] =~ /\.(.*)$/
|
27
|
+
|
28
|
+
Config::App.resources.each_pair do |name, path|
|
29
|
+
resource_path = File.join(path, env['PATH_INFO'])
|
30
|
+
next unless File.exists?(resource_path)
|
31
|
+
return true, resource_path
|
32
|
+
end
|
33
|
+
|
34
|
+
return false
|
24
35
|
end
|
25
36
|
end
|
26
37
|
end
|
27
38
|
end
|
39
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Pakyow
|
2
|
+
class MultiLog
|
3
|
+
def initialize(*targets)
|
4
|
+
@targets = targets
|
5
|
+
end
|
6
|
+
|
7
|
+
def write(*args)
|
8
|
+
@targets.each { |t| t.write(*args) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def close
|
12
|
+
@targets.each(&:close)
|
13
|
+
end
|
14
|
+
|
15
|
+
def flush
|
16
|
+
@targets.each(&:flush)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,61 +2,81 @@ module Pakyow
|
|
2
2
|
|
3
3
|
# The Request object.
|
4
4
|
class Request < Rack::Request
|
5
|
-
attr_accessor :restful, :route_path, :controller, :action, :format,
|
5
|
+
attr_accessor :restful, :route_path, :controller, :action, :format,
|
6
|
+
:error, :app, :path, :method, :paths, :methods, :formats
|
6
7
|
|
7
8
|
def initialize(*args)
|
8
9
|
super
|
9
10
|
|
10
|
-
|
11
|
+
@paths = []
|
12
|
+
@methods = []
|
13
|
+
@formats = []
|
14
|
+
|
15
|
+
@path = path_info
|
16
|
+
@method = request_method.downcase.to_sym
|
11
17
|
end
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
19
|
+
def path=(path)
|
20
|
+
@paths << path
|
21
|
+
@path = path
|
16
22
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
23
|
+
|
24
|
+
def method=(method)
|
25
|
+
@methods << method
|
26
|
+
@method = method
|
21
27
|
end
|
22
28
|
|
23
29
|
def format=(format)
|
24
|
-
|
25
|
-
|
30
|
+
format = format ? format.to_sym : :html
|
31
|
+
@formats << format
|
32
|
+
@format = format
|
33
|
+
|
26
34
|
# Set response type
|
27
|
-
|
35
|
+
@app.response["Content-Type"] = Rack::Mime.mime_type(".#{@format}")
|
36
|
+
end
|
37
|
+
|
38
|
+
def first_path
|
39
|
+
@paths[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
def first_method
|
43
|
+
@methods[0]
|
44
|
+
end
|
45
|
+
|
46
|
+
def first_format
|
47
|
+
@formats[0]
|
28
48
|
end
|
29
49
|
|
30
50
|
def session
|
31
51
|
self.env['rack.session'] || {}
|
32
52
|
end
|
33
|
-
|
53
|
+
|
34
54
|
def cookies
|
35
55
|
@cookies ||= HashUtils.strhash(super)
|
36
56
|
end
|
37
|
-
|
57
|
+
|
38
58
|
# Returns indifferent params (see {HashUtils.strhash} for more info on indifferent hashes).
|
39
59
|
def params
|
40
60
|
@params ||= HashUtils.strhash(super)
|
41
61
|
end
|
42
|
-
|
62
|
+
|
43
63
|
# Returns array of url components.
|
44
64
|
def path_parts
|
45
|
-
@url ||=
|
65
|
+
@url ||= path ? self.class.split_url(path) : []
|
46
66
|
end
|
47
67
|
|
48
68
|
def referer
|
49
|
-
@referer ||=
|
69
|
+
@referer ||= env['HTTP_REFERER']
|
50
70
|
end
|
51
|
-
|
71
|
+
|
52
72
|
# Returns array of referer components.
|
53
73
|
def referer_parts
|
54
|
-
@referer_parts ||=
|
74
|
+
@referer_parts ||= referer ? self.class.split_url(referer) : []
|
55
75
|
end
|
56
76
|
|
57
|
-
def setup(path, method = nil)
|
58
|
-
|
59
|
-
|
77
|
+
def setup(path = self.path, method = nil)
|
78
|
+
set_request_format_from_path(path)
|
79
|
+
set_working_path_from_path(path, method)
|
60
80
|
end
|
61
81
|
|
62
82
|
#TODO move to util class
|
@@ -65,25 +85,27 @@ module Pakyow
|
|
65
85
|
url.split('/').each { |r|
|
66
86
|
arr << r unless r.empty?
|
67
87
|
}
|
68
|
-
|
88
|
+
|
69
89
|
return arr
|
70
90
|
end
|
71
|
-
|
91
|
+
|
92
|
+
def has_route_vars?
|
93
|
+
return false if @route_path.nil?
|
94
|
+
return false if @route_path.is_a?(Regexp)
|
95
|
+
return true if @route_path.index(':')
|
96
|
+
end
|
97
|
+
|
72
98
|
protected
|
73
99
|
|
74
100
|
def set_working_path_from_path(path, method)
|
75
101
|
base_route, ignore_format = StringUtils.split_at_last_dot(path)
|
76
102
|
|
77
|
-
self.
|
78
|
-
self.
|
103
|
+
self.path = base_route
|
104
|
+
self.method = method || self.method
|
79
105
|
end
|
80
106
|
|
81
107
|
def set_request_format_from_path(path)
|
82
108
|
path, format = StringUtils.split_at_last_dot(path)
|
83
|
-
|
84
|
-
#TODO why it no work without this? was working fine in application
|
85
|
-
return unless format
|
86
|
-
|
87
109
|
self.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
|
88
110
|
end
|
89
111
|
end
|