pakyow-core 0.8.rc4 → 0.8.0
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/pakyow-core/CHANGES +4 -0
- data/pakyow-core/lib/core/app.rb +51 -50
- data/pakyow-core/lib/core/app_context.rb +10 -0
- data/pakyow-core/lib/core/base.rb +4 -1
- data/pakyow-core/lib/core/errors.rb +13 -0
- data/pakyow-core/lib/core/helpers.rb +6 -3
- data/pakyow-core/lib/core/loader.rb +5 -5
- data/pakyow-core/lib/core/middleware/static.rb +3 -2
- data/pakyow-core/lib/core/request.rb +8 -9
- data/pakyow-core/lib/core/response.rb +12 -0
- data/pakyow-core/lib/core/route_eval.rb +252 -159
- data/pakyow-core/lib/core/route_lookup.rb +4 -5
- data/pakyow-core/lib/core/route_merger.rb +76 -0
- data/pakyow-core/lib/core/route_module.rb +21 -0
- data/pakyow-core/lib/core/route_set.rb +15 -8
- data/pakyow-core/lib/core/route_template_defaults.rb +29 -31
- data/pakyow-core/lib/core/router.rb +15 -10
- data/pakyow-core/lib/utils/dir.rb +6 -3
- data/pakyow-core/lib/utils/hash.rb +32 -29
- data/pakyow-core/lib/utils/string.rb +30 -27
- metadata +15 -12
- data/pakyow-core/lib/core/exceptions.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a272d5c2f6d429275df4e3eac0561c8df6c285e3
|
4
|
+
data.tar.gz: 8b21f4193337cd9c7298ccbe0e004bd9c814beb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbb4242d0cbbb4dcce94608b6773026e68c4168c450dd4e7587def70a3db921d5e6d53a7b9cd45b3f718451ec70c8b7cf7878ea998eacf95aed655dc084cea56
|
7
|
+
data.tar.gz: b965ed0dd836899da344beb011cd777eb09080fa3013c381d7a4e1194108147f90c58f9be3dfcb0dedce8d6c06519a66d78ea85188a10c992280cb1506173f07
|
data/pakyow-core/CHANGES
CHANGED
data/pakyow-core/lib/core/app.rb
CHANGED
@@ -4,6 +4,7 @@ module Pakyow
|
|
4
4
|
def reset
|
5
5
|
@@routes = {}
|
6
6
|
@@config = {}
|
7
|
+
@@middleware = []
|
7
8
|
|
8
9
|
@@stacks = {:before => {}, :after => {}}
|
9
10
|
%w(init load process route match error).each {|name|
|
@@ -16,7 +17,7 @@ module Pakyow
|
|
16
17
|
#
|
17
18
|
def define(&block)
|
18
19
|
# sets the path to the app file so it can be reloaded later
|
19
|
-
config.app.path =
|
20
|
+
config.app.path = Utils::String.parse_path_from_caller(caller[0])
|
20
21
|
|
21
22
|
self.instance_eval(&block)
|
22
23
|
end
|
@@ -32,15 +33,10 @@ module Pakyow
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
#
|
36
|
+
# Accepts block to be added to middleware stack.
|
36
37
|
#
|
37
38
|
def middleware(&block)
|
38
|
-
|
39
|
-
# request when auto_reload is enabled
|
40
|
-
return if prepared?
|
41
|
-
|
42
|
-
# tell builder about the middleware
|
43
|
-
builder.instance_eval(&block)
|
39
|
+
@@middleware << block
|
44
40
|
end
|
45
41
|
|
46
42
|
# Creates an environment.
|
@@ -144,7 +140,11 @@ module Pakyow
|
|
144
140
|
envs = envs.empty? || envs.first.nil? ? [config.app.default_environment] : envs
|
145
141
|
load_config(envs)
|
146
142
|
|
147
|
-
# load middleware
|
143
|
+
# load each block from middleware stack
|
144
|
+
@@middleware.each {|mw|
|
145
|
+
self.instance_exec(builder, &mw)
|
146
|
+
}
|
147
|
+
|
148
148
|
builder.use(Rack::MethodOverride)
|
149
149
|
builder.use(Middleware::Static) if config.app.static
|
150
150
|
builder.use(Middleware::Logger) if config.app.log
|
@@ -185,7 +185,7 @@ module Pakyow
|
|
185
185
|
include Helpers
|
186
186
|
include AppHelpers
|
187
187
|
|
188
|
-
|
188
|
+
attr_writer :context
|
189
189
|
|
190
190
|
def initialize
|
191
191
|
Pakyow.app = self
|
@@ -217,42 +217,43 @@ module Pakyow
|
|
217
217
|
def process(env)
|
218
218
|
call_stack(:before, :process)
|
219
219
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
220
|
+
req = Request.new(env)
|
221
|
+
res = Response.new
|
222
|
+
|
223
|
+
# set response format based on request
|
224
|
+
res.format = req.format
|
225
|
+
|
226
|
+
@context = AppContext.new(req, res)
|
224
227
|
|
225
228
|
set_initial_cookies
|
226
229
|
|
227
230
|
@found = false
|
228
231
|
catch(:halt) {
|
229
|
-
|
230
|
-
call_stack(:before, :route)
|
232
|
+
call_stack(:before, :route)
|
231
233
|
|
232
|
-
|
233
|
-
|
234
|
-
|
234
|
+
@found = @router.perform(context, self) {
|
235
|
+
call_stack(:after, :match)
|
236
|
+
}
|
235
237
|
|
236
|
-
|
237
|
-
end
|
238
|
+
call_stack(:after, :route)
|
238
239
|
|
239
240
|
unless found?
|
240
|
-
handle(404, false)
|
241
|
+
handle(404, false)
|
241
242
|
|
242
243
|
if config.app.errors_in_browser
|
243
|
-
|
244
|
+
response["Content-Type"] = 'text/html'
|
244
245
|
|
245
246
|
view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '404.html')
|
246
247
|
content = File.open(view_file).read
|
247
248
|
|
248
|
-
path =
|
249
|
+
path = Utils::String.normalize_path(request.path)
|
249
250
|
path = '/' if path.empty?
|
250
251
|
|
251
252
|
content.gsub!('{view_path}', path == '/' ? 'index.html' : "#{path}.html")
|
252
253
|
content.gsub!('{route_path}', path)
|
253
254
|
|
254
|
-
|
255
|
-
|
255
|
+
response.body = []
|
256
|
+
response.body << content
|
256
257
|
end
|
257
258
|
end
|
258
259
|
}
|
@@ -261,38 +262,38 @@ module Pakyow
|
|
261
262
|
|
262
263
|
call_stack(:after, :process)
|
263
264
|
|
264
|
-
|
265
|
+
response.finish
|
265
266
|
rescue StandardError => error
|
266
267
|
call_stack(:before, :error)
|
267
268
|
|
268
|
-
|
269
|
+
request.error = error
|
269
270
|
|
270
271
|
handle(500, false) unless found?
|
271
272
|
|
272
273
|
if config.app.errors_in_browser
|
273
|
-
|
274
|
-
|
274
|
+
response["Content-Type"] = 'text/html'
|
275
|
+
|
275
276
|
view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '500.html')
|
276
277
|
content = File.open(view_file).read
|
277
278
|
|
278
|
-
path =
|
279
|
+
path = Utils::String.normalize_path(request.path)
|
279
280
|
path = '/' if path.empty?
|
280
281
|
|
281
282
|
nice_source = error.backtrace[0].match(/^(.+?):(\d+)(|:in `(.+)')$/)
|
282
283
|
|
283
284
|
content.gsub!('{file}', nice_source[1].gsub(File.expand_path(Config::App.root) + '/', ''))
|
284
285
|
content.gsub!('{line}', nice_source[2])
|
285
|
-
|
286
|
-
content.gsub!('{msg}', error.to_s)
|
287
|
-
content.gsub!('{trace}', error.backtrace.join('<br>'))
|
288
286
|
|
289
|
-
|
290
|
-
|
287
|
+
content.gsub!('{msg}', CGI.escapeHTML(error.to_s))
|
288
|
+
content.gsub!('{trace}', error.backtrace.map { |bt| CGI.escapeHTML(bt) }.join('<br>'))
|
289
|
+
|
290
|
+
response.body = []
|
291
|
+
response.body << content
|
291
292
|
end
|
292
293
|
|
293
294
|
call_stack(:after, :error)
|
294
295
|
|
295
|
-
|
296
|
+
response.finish
|
296
297
|
end
|
297
298
|
|
298
299
|
def found?
|
@@ -319,17 +320,17 @@ module Pakyow
|
|
319
320
|
# Interrupts the application and returns response immediately.
|
320
321
|
#
|
321
322
|
def halt
|
322
|
-
throw :halt,
|
323
|
+
throw :halt, response
|
323
324
|
end
|
324
325
|
|
325
326
|
# Routes the request to different logic.
|
326
327
|
#
|
327
328
|
def reroute(path, method = nil)
|
328
|
-
|
329
|
+
request.setup(path, method)
|
329
330
|
|
330
331
|
call_stack(:before, :route)
|
331
332
|
call_stack(:after, :match)
|
332
|
-
@router.reroute(
|
333
|
+
@router.reroute(request)
|
333
334
|
call_stack(:after, :route)
|
334
335
|
end
|
335
336
|
|
@@ -344,7 +345,7 @@ module Pakyow
|
|
344
345
|
data = file_or_data.read
|
345
346
|
|
346
347
|
# auto set type based on file type
|
347
|
-
type = Rack::Mime.mime_type("." +
|
348
|
+
type = Rack::Mime.mime_type("." + Utils::String.split_at_last_dot(file_or_data.path)[1])
|
348
349
|
else
|
349
350
|
data = file_or_data
|
350
351
|
end
|
@@ -353,7 +354,7 @@ module Pakyow
|
|
353
354
|
headers["Content-Type"] = type if type
|
354
355
|
headers["Content-disposition"] = "attachment; filename=#{send_as}" if send_as
|
355
356
|
|
356
|
-
|
357
|
+
self.context = AppContext.new(request, Response.new(data, response.status, response.header.merge(headers)))
|
357
358
|
halt
|
358
359
|
end
|
359
360
|
|
@@ -361,11 +362,11 @@ module Pakyow
|
|
361
362
|
#
|
362
363
|
def redirect(location, status_code = 302)
|
363
364
|
location = router.path(location) if location.is_a?(Symbol)
|
364
|
-
|
365
|
+
|
365
366
|
headers = response ? response.header : {}
|
366
367
|
headers = headers.merge({'Location' => location})
|
367
368
|
|
368
|
-
|
369
|
+
self.context = AppContext.new(request, Response.new('', status_code, headers))
|
369
370
|
halt
|
370
371
|
end
|
371
372
|
|
@@ -409,18 +410,18 @@ module Pakyow
|
|
409
410
|
@router = Router.instance.reset
|
410
411
|
self.class.routes.each_pair {|set_name, block|
|
411
412
|
@router.set(set_name, &block)
|
412
|
-
}
|
413
|
+
} unless config.app.ignore_routes
|
413
414
|
end
|
414
415
|
|
415
416
|
def set_cookies
|
416
|
-
|
417
|
-
|
417
|
+
request.cookies.each_pair {|k, v|
|
418
|
+
response.unset_cookie(k) if v.nil?
|
418
419
|
|
419
420
|
# cookie is already set with value, ignore
|
420
421
|
next if @initial_cookies.include?(k.to_s) && @initial_cookies[k.to_s] == v
|
421
422
|
|
422
423
|
# set cookie with defaults
|
423
|
-
|
424
|
+
response.set_cookie(k, {
|
424
425
|
:path => config.cookies.path,
|
425
426
|
:expires => config.cookies.expiration,
|
426
427
|
:value => v
|
@@ -429,7 +430,7 @@ module Pakyow
|
|
429
430
|
|
430
431
|
# delete cookies that are no longer present
|
431
432
|
@initial_cookies.each {|k|
|
432
|
-
|
433
|
+
response.delete_cookie(k) unless request.cookies.key?(k.to_s)
|
433
434
|
}
|
434
435
|
end
|
435
436
|
|
@@ -437,7 +438,7 @@ module Pakyow
|
|
437
438
|
# for comparison at the end of the cycle
|
438
439
|
def set_initial_cookies
|
439
440
|
@initial_cookies = {}
|
440
|
-
|
441
|
+
request.cookies.each {|k,v|
|
441
442
|
@initial_cookies[k] = v
|
442
443
|
}
|
443
444
|
end
|
@@ -5,16 +5,19 @@ require 'core/config/cookies'
|
|
5
5
|
require 'core/config/logger'
|
6
6
|
require 'core/helpers'
|
7
7
|
require 'core/multilog'
|
8
|
+
require 'core/app_context'
|
8
9
|
require 'core/request'
|
9
10
|
require 'core/response'
|
10
11
|
require 'core/loader'
|
11
12
|
require 'core/router'
|
13
|
+
require 'core/route_merger'
|
14
|
+
require 'core/route_module'
|
12
15
|
require 'core/route_set'
|
13
16
|
require 'core/route_eval'
|
14
17
|
require 'core/route_template_defaults'
|
15
18
|
require 'core/route_lookup'
|
16
19
|
require 'core/app'
|
17
|
-
require 'core/
|
20
|
+
require 'core/errors'
|
18
21
|
|
19
22
|
# middlewares
|
20
23
|
require 'core/middleware/logger'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Pakyow
|
2
|
+
# Raised when no app context is available
|
3
|
+
class NoContextError < StandardError; end
|
4
|
+
|
5
|
+
# Raised when route is looked up that doesn't exist
|
6
|
+
class MissingRoute < StandardError; end
|
7
|
+
|
8
|
+
# Raised when template part doesn't exist
|
9
|
+
class UnknownTemplatePart < StandardError; end
|
10
|
+
|
11
|
+
class Error < StandardError; end
|
12
|
+
end
|
13
|
+
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module Pakyow
|
2
|
-
|
3
2
|
# For methods that should be accessible anywhere
|
4
3
|
module Helpers
|
4
|
+
def context
|
5
|
+
@context or raise NoContextError
|
6
|
+
end
|
7
|
+
|
5
8
|
def logger
|
6
9
|
request.logger
|
7
10
|
end
|
@@ -11,12 +14,12 @@ module Pakyow
|
|
11
14
|
end
|
12
15
|
|
13
16
|
def request
|
14
|
-
|
17
|
+
context.request
|
15
18
|
end
|
16
19
|
alias_method :req, :request
|
17
20
|
|
18
21
|
def response
|
19
|
-
|
22
|
+
context.response
|
20
23
|
end
|
21
24
|
alias_method :res, :response
|
22
25
|
|
@@ -7,21 +7,21 @@ module Pakyow
|
|
7
7
|
def load_from_path(path)
|
8
8
|
require_recursively(path)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
protected
|
12
|
-
|
12
|
+
|
13
13
|
def require_recursively(dir)
|
14
14
|
@times ||= {}
|
15
15
|
if File.exists?(dir)
|
16
|
-
|
16
|
+
Utils::Dir.walk_dir(dir) do |path|
|
17
17
|
next if FileTest.directory?(path)
|
18
18
|
next if path.split('.')[-1] != 'rb'
|
19
|
-
|
19
|
+
|
20
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)
|
24
|
-
end
|
24
|
+
end
|
25
25
|
else
|
26
26
|
require path
|
27
27
|
end
|
@@ -11,8 +11,9 @@ module Pakyow
|
|
11
11
|
if static
|
12
12
|
catch(:halt) do
|
13
13
|
app = Pakyow.app.dup
|
14
|
-
|
15
|
-
|
14
|
+
res = Response.new
|
15
|
+
req = Request.new(env)
|
16
|
+
app.context = AppContext.new(req, res)
|
16
17
|
app.send(File.open(resource_path))
|
17
18
|
end
|
18
19
|
else
|
@@ -2,8 +2,8 @@ module Pakyow
|
|
2
2
|
|
3
3
|
# The Request object.
|
4
4
|
class Request < Rack::Request
|
5
|
-
attr_accessor :restful, :route_path, :controller, :action, :format,
|
6
|
-
:error, :
|
5
|
+
attr_accessor :restful, :route_path, :controller, :action, :format,
|
6
|
+
:error, :path, :method, :paths, :methods, :formats
|
7
7
|
|
8
8
|
def initialize(*args)
|
9
9
|
super
|
@@ -14,6 +14,8 @@ module Pakyow
|
|
14
14
|
|
15
15
|
@path = path_info
|
16
16
|
@method = request_method.downcase.to_sym
|
17
|
+
|
18
|
+
setup
|
17
19
|
end
|
18
20
|
|
19
21
|
def path=(path)
|
@@ -30,9 +32,6 @@ module Pakyow
|
|
30
32
|
format = format ? format.to_sym : :html
|
31
33
|
@formats << format
|
32
34
|
@format = format
|
33
|
-
|
34
|
-
# Set response type
|
35
|
-
@app.response["Content-Type"] = Rack::Mime.mime_type(".#{@format}")
|
36
35
|
end
|
37
36
|
|
38
37
|
def first_path
|
@@ -52,12 +51,12 @@ module Pakyow
|
|
52
51
|
end
|
53
52
|
|
54
53
|
def cookies
|
55
|
-
@cookies ||=
|
54
|
+
@cookies ||= Utils::Hash.strhash(super)
|
56
55
|
end
|
57
56
|
|
58
57
|
# Returns indifferent params (see {HashUtils.strhash} for more info on indifferent hashes).
|
59
58
|
def params
|
60
|
-
@params ||=
|
59
|
+
@params ||= Utils::Hash.strhash(super)
|
61
60
|
end
|
62
61
|
|
63
62
|
# Returns array of url components.
|
@@ -98,14 +97,14 @@ module Pakyow
|
|
98
97
|
protected
|
99
98
|
|
100
99
|
def set_working_path_from_path(path, method)
|
101
|
-
base_route, ignore_format =
|
100
|
+
base_route, ignore_format = Utils::String.split_at_last_dot(path)
|
102
101
|
|
103
102
|
self.path = base_route
|
104
103
|
self.method = method || self.method
|
105
104
|
end
|
106
105
|
|
107
106
|
def set_request_format_from_path(path)
|
108
|
-
path, format =
|
107
|
+
path, format = Utils::String.split_at_last_dot(path)
|
109
108
|
self.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
|
110
109
|
end
|
111
110
|
end
|