pakyow-core 0.8rc1 → 0.8.rc4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|