orange-core 0.5.3
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.
- data/README.markdown +145 -0
- data/lib/orange-core.rb +8 -0
- data/lib/orange-core/application.rb +132 -0
- data/lib/orange-core/assets/css/exceptions.css +50 -0
- data/lib/orange-core/assets/js/exceptions.js +44 -0
- data/lib/orange-core/carton.rb +178 -0
- data/lib/orange-core/core.rb +266 -0
- data/lib/orange-core/magick.rb +270 -0
- data/lib/orange-core/middleware/base.rb +96 -0
- data/lib/orange-core/middleware/database.rb +45 -0
- data/lib/orange-core/middleware/four_oh_four.rb +45 -0
- data/lib/orange-core/middleware/globals.rb +17 -0
- data/lib/orange-core/middleware/loader.rb +13 -0
- data/lib/orange-core/middleware/rerouter.rb +53 -0
- data/lib/orange-core/middleware/restful_router.rb +99 -0
- data/lib/orange-core/middleware/route_context.rb +39 -0
- data/lib/orange-core/middleware/route_site.rb +51 -0
- data/lib/orange-core/middleware/show_exceptions.rb +80 -0
- data/lib/orange-core/middleware/static.rb +67 -0
- data/lib/orange-core/middleware/static_file.rb +32 -0
- data/lib/orange-core/middleware/template.rb +60 -0
- data/lib/orange-core/packet.rb +232 -0
- data/lib/orange-core/plugin.rb +172 -0
- data/lib/orange-core/resource.rb +96 -0
- data/lib/orange-core/resources/mapper.rb +36 -0
- data/lib/orange-core/resources/model_resource.rb +228 -0
- data/lib/orange-core/resources/not_found.rb +10 -0
- data/lib/orange-core/resources/page_parts.rb +68 -0
- data/lib/orange-core/resources/parser.rb +113 -0
- data/lib/orange-core/resources/routable_resource.rb +16 -0
- data/lib/orange-core/resources/scaffold.rb +106 -0
- data/lib/orange-core/stack.rb +226 -0
- data/lib/orange-core/templates/exceptions.haml +111 -0
- data/lib/orange-core/views/default_resource/create.haml +4 -0
- data/lib/orange-core/views/default_resource/edit.haml +9 -0
- data/lib/orange-core/views/default_resource/list.haml +10 -0
- data/lib/orange-core/views/default_resource/show.haml +4 -0
- data/lib/orange-core/views/default_resource/table_row.haml +7 -0
- data/lib/orange-core/views/not_found/404.haml +2 -0
- data/spec/orange-core/application_spec.rb +183 -0
- data/spec/orange-core/carton_spec.rb +136 -0
- data/spec/orange-core/core_spec.rb +248 -0
- data/spec/orange-core/magick_spec.rb +96 -0
- data/spec/orange-core/middleware/base_spec.rb +38 -0
- data/spec/orange-core/middleware/globals_spec.rb +3 -0
- data/spec/orange-core/middleware/rerouter_spec.rb +3 -0
- data/spec/orange-core/middleware/restful_router_spec.rb +3 -0
- data/spec/orange-core/middleware/route_context_spec.rb +3 -0
- data/spec/orange-core/middleware/route_site_spec.rb +3 -0
- data/spec/orange-core/middleware/show_exceptions_spec.rb +3 -0
- data/spec/orange-core/middleware/static_file_spec.rb +3 -0
- data/spec/orange-core/middleware/static_spec.rb +3 -0
- data/spec/orange-core/mock/mock_app.rb +16 -0
- data/spec/orange-core/mock/mock_carton.rb +43 -0
- data/spec/orange-core/mock/mock_core.rb +2 -0
- data/spec/orange-core/mock/mock_middleware.rb +25 -0
- data/spec/orange-core/mock/mock_mixins.rb +19 -0
- data/spec/orange-core/mock/mock_model_resource.rb +47 -0
- data/spec/orange-core/mock/mock_pulp.rb +24 -0
- data/spec/orange-core/mock/mock_resource.rb +26 -0
- data/spec/orange-core/mock/mock_router.rb +10 -0
- data/spec/orange-core/orange_spec.rb +19 -0
- data/spec/orange-core/packet_spec.rb +203 -0
- data/spec/orange-core/resource_spec.rb +96 -0
- data/spec/orange-core/resources/mapper_spec.rb +5 -0
- data/spec/orange-core/resources/model_resource_spec.rb +246 -0
- data/spec/orange-core/resources/parser_spec.rb +5 -0
- data/spec/orange-core/resources/routable_resource_spec.rb +5 -0
- data/spec/orange-core/spec_helper.rb +53 -0
- data/spec/orange-core/stack_spec.rb +232 -0
- data/spec/stats.rb +182 -0
- metadata +227 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'orange-core/packet'
|
2
|
+
|
3
|
+
# Orange Middleware is a bit more complex than Rack middleware.
|
4
|
+
# Initializing it requires both a link to the downstream app and
|
5
|
+
# the core, and calling the app often requires an Orange::Packet
|
6
|
+
#
|
7
|
+
# Orange::Middleware::Base takes care of these basic tasks.
|
8
|
+
# Subclasses override the init method for extra initialization
|
9
|
+
# and the packet_call for a call with a packet, rather than
|
10
|
+
# a basic call
|
11
|
+
module Orange::Middleware
|
12
|
+
class Base
|
13
|
+
# Initialize will set the core and downstream app, then call init
|
14
|
+
# subclasses should override init instead of initialize.
|
15
|
+
# If the subclass defines a stack_init, then it will be registered
|
16
|
+
# as a stack_loaded event.
|
17
|
+
# @param [Object] app a downstream app
|
18
|
+
# @param [Orange::Core] core the orange core
|
19
|
+
# @param [optional, Array] args any arguments
|
20
|
+
def initialize(app, core, *args)
|
21
|
+
@app = app
|
22
|
+
@core = core
|
23
|
+
init(*args)
|
24
|
+
core.middleware(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
# A stub method that subclasses can override to handle initialization
|
28
|
+
# For initialization
|
29
|
+
# @return [void]
|
30
|
+
def init(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
# The standard Rack "call". By default, Orange Middleware wraps the env into
|
34
|
+
# an Orange::Packet and passes it on to #packet_call. Subclasses will typically
|
35
|
+
# override packet_call rather than overriding call directly.
|
36
|
+
#
|
37
|
+
# Orange Middleware
|
38
|
+
# should expect to have this method ignored by upstream Orange-aware apps in
|
39
|
+
# favor of calling packet_call directly.
|
40
|
+
# @param [Hash] env the hash of environment variables given by the rack interface.
|
41
|
+
# @return [Array] the standard Rack striplet of status, headers and content
|
42
|
+
def call(env)
|
43
|
+
packet = Orange::Packet.new(@core, env)
|
44
|
+
packet_call(packet)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Like the standard call, but with the env hash already wrapped into a Packet
|
48
|
+
# This is called automatically as part of #call, so subclasses can have a packet
|
49
|
+
# without having to initialize it. It will be called directly by Orange-aware
|
50
|
+
# upstream middleware, skipping the step of initializing the packet during #call.
|
51
|
+
#
|
52
|
+
# Passing the packet downstream should be done with #pass rather than the Rack
|
53
|
+
# standard @app.call, since #pass will take the packet and do a #packet_call
|
54
|
+
# if possible.
|
55
|
+
# @param [Orange::Packet] packet the packet corresponding to this env
|
56
|
+
# @return [Array] the standard Rack striplet of status, headers and content
|
57
|
+
def packet_call(packet)
|
58
|
+
pass packet
|
59
|
+
end
|
60
|
+
|
61
|
+
# Pass will sent the packet to the downstream app by calling call or packet call.
|
62
|
+
# Calling pass on a packet is the preferred way to call downstream apps, as it
|
63
|
+
# will call packet_call directly if possible (to avoid reinitializing the packet)
|
64
|
+
# @param [Orange::Packet] packet the packet to pass to downstream apps
|
65
|
+
# @return [Array] the standard Rack striplet of status, headers and content
|
66
|
+
def pass(packet)
|
67
|
+
if @app.respond_to?(:packet_call)
|
68
|
+
@app.packet_call(packet)
|
69
|
+
else
|
70
|
+
recapture(@app.call(packet.env), packet)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# After the pass has been completed, we should recapture the contents and make
|
75
|
+
# sure they are placed in the packet, in case the downstream app is not Orange aware.
|
76
|
+
# @param [Array] the standard Rack striplet of status, headers and content
|
77
|
+
# @param [Orange::Packet] packet the packet to pass to downstream apps
|
78
|
+
# @return [Array] the standard Rack striplet of status, headers and content
|
79
|
+
def recapture(response, packet)
|
80
|
+
packet[:status] = response[0]
|
81
|
+
packet[:headers] = response[1]
|
82
|
+
packet[:content] = response[2].first
|
83
|
+
response
|
84
|
+
end
|
85
|
+
|
86
|
+
# Accessor for @core, which is the stack's instance of Orange::Core
|
87
|
+
# @return [Orange::Core] the stack's instance of Orange::Core
|
88
|
+
def orange; @core; end
|
89
|
+
|
90
|
+
# Help stack traces
|
91
|
+
# @return [String] string representing this middleware (#to_s)
|
92
|
+
def inspect
|
93
|
+
self.to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
module Orange::Middleware
|
3
|
+
|
4
|
+
class Database < Base
|
5
|
+
def init(opts = {})
|
6
|
+
opts = opts.with_defaults(:migration_url => (orange.options[:development_mode] ? '/__ORANGE_DB__/migrate' : false), :no_auto_upgrade => false)
|
7
|
+
orange.mixin Orange::Mixins::DBLoader
|
8
|
+
@options = opts
|
9
|
+
end
|
10
|
+
|
11
|
+
def stack_init
|
12
|
+
unless orange.options.has_key?('database') && orange.options['database'] == false
|
13
|
+
db = orange.options['database'] || 'sqlite3::memory:'
|
14
|
+
orange.load_db!(db)
|
15
|
+
orange.upgrade_db! unless @options[:no_auto_upgrade] || orange.options['db_no_auto_upgrade']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def packet_call(packet)
|
20
|
+
path = packet['route.path'] || packet.request.path_info
|
21
|
+
if @options[:migration_url] && @options[:migration_url] == path
|
22
|
+
orange.migrate_db!
|
23
|
+
after = packet.flash('redirect_to') || '/'
|
24
|
+
packet.reroute(after)
|
25
|
+
end
|
26
|
+
pass packet
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
module Orange::Mixins::DBLoader
|
33
|
+
def load_db!(url)
|
34
|
+
DataMapper.setup(:default, url)
|
35
|
+
end
|
36
|
+
|
37
|
+
def migrate_db!
|
38
|
+
DataMapper.auto_migrate!
|
39
|
+
end
|
40
|
+
|
41
|
+
def upgrade_db!
|
42
|
+
DataMapper.auto_upgrade!
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
|
3
|
+
module Orange::Middleware
|
4
|
+
# The FlexRouter middleware takes a resource that can route paths and
|
5
|
+
# then intercepts routes for that resource. By default,
|
6
|
+
# it uses the Orange::SitemapResource.
|
7
|
+
#
|
8
|
+
# The resource is automatically loaded into the core as
|
9
|
+
# :sitemap. The resource must respond to "route?(path)"
|
10
|
+
# and "route(packet)".
|
11
|
+
#
|
12
|
+
# Pass a different routing resource using the :resource arg
|
13
|
+
class FourOhFour < Base
|
14
|
+
def init(opts = {})
|
15
|
+
@resource = opts[:resource] || Orange::NotFound
|
16
|
+
orange.load @resource.new, :not_found
|
17
|
+
orange.add_pulp Orange::Pulp::NotFoundHelper
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sets the sitemap resource as the router if the resource can accept
|
21
|
+
# the path.
|
22
|
+
def packet_call(packet)
|
23
|
+
packet['route.router'] = orange[:not_found] unless packet['route.router']
|
24
|
+
begin
|
25
|
+
pass packet
|
26
|
+
rescue Orange::NotFoundException
|
27
|
+
orange[:not_found].route(packet)
|
28
|
+
packet.finish
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Orange
|
36
|
+
class NotFoundException < Exception
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
module Pulp::NotFoundHelper
|
41
|
+
def not_found
|
42
|
+
raise Orange::NotFoundException.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
module Orange::Middleware
|
3
|
+
|
4
|
+
class Globals < Base
|
5
|
+
def init(opts = {})
|
6
|
+
opts = opts.with_defaults(:file => "__ORANGE__/config.yml")
|
7
|
+
@file = opts[:file].gsub('__ORANGE__', orange.app_dir)
|
8
|
+
@globals = orange[:parser].yaml(@file) || {}
|
9
|
+
@globals.each{|k,v| orange.options[k] = v}
|
10
|
+
end
|
11
|
+
def packet_call(packet)
|
12
|
+
packet['orange.globals'] ||= orange.options
|
13
|
+
pass packet
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
module Orange::Middleware
|
3
|
+
class Loader < Base
|
4
|
+
def init(*args)
|
5
|
+
Dir.glob(File.join(orange.app_dir, 'resources', '*.rb')).each do |f|
|
6
|
+
require f
|
7
|
+
orange.load Orange::Inflector.constantize(Orange::Inflector.camelize(File.basename(f, '.rb'))).new
|
8
|
+
end
|
9
|
+
Dir.glob(File.join(orange.app_dir, 'cartons', '*.rb')).each { |f| require f }
|
10
|
+
Dir.glob(File.join(orange.app_dir, 'middleware', '*.rb')).each { |f| require f }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
module Orange::Middleware
|
3
|
+
|
4
|
+
class Rerouter < Base
|
5
|
+
def init(*args)
|
6
|
+
orange.add_pulp Orange::Pulp::Packet_Reroute
|
7
|
+
end
|
8
|
+
|
9
|
+
def packet_call(packet)
|
10
|
+
begin
|
11
|
+
pass packet
|
12
|
+
rescue Orange::Reroute
|
13
|
+
packet.finish
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Orange
|
20
|
+
|
21
|
+
module Pulp::Packet_Reroute
|
22
|
+
def reroute(url, type = :real, *args)
|
23
|
+
packet['reroute.to'] = url
|
24
|
+
packet['reroute.type'] = type
|
25
|
+
packet['reroute.args'] = *args if args
|
26
|
+
raise Reroute.new(self), 'Unhandled reroute'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Reroute < Exception
|
31
|
+
def initialize(packet)
|
32
|
+
@packet = packet
|
33
|
+
@packet[:headers] = {"Content-Type" => 'text/html', "Location" => self.url}
|
34
|
+
@packet[:status] = 302
|
35
|
+
end
|
36
|
+
|
37
|
+
def url
|
38
|
+
case packet['reroute.type']
|
39
|
+
when :real
|
40
|
+
packet['reroute.to']
|
41
|
+
# Parsing for orange urls or something
|
42
|
+
when :orange
|
43
|
+
packet.route_to(packet['reroute.to'], *packet['reroute.args', []])
|
44
|
+
else
|
45
|
+
packet['reroute.to']
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def packet
|
50
|
+
@packet
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
|
3
|
+
module Orange::Middleware
|
4
|
+
class RestfulRouter < Base
|
5
|
+
def init(*args)
|
6
|
+
opts = args.extract_options!.with_defaults(:restful_contexts => [:admin, :orange], :not_found => false, :exposed_actions => {:admin => :all, :orange => :all})
|
7
|
+
@exposed = opts[:exposed_actions]
|
8
|
+
@contexts = opts[:restful_contexts]
|
9
|
+
@not_found = opts[:not_found]
|
10
|
+
end
|
11
|
+
|
12
|
+
# sets resource, resource_id, resource_action and resource_path
|
13
|
+
# /resource/id/action/[resource/path/if/any]
|
14
|
+
# /resource/action/[resource/path/if/any]
|
15
|
+
#
|
16
|
+
# In future - support for nested resources
|
17
|
+
def packet_call(packet)
|
18
|
+
return (pass packet) if packet['route.router'] # Don't route if other middleware
|
19
|
+
# already has
|
20
|
+
parts = route_parts(packet)
|
21
|
+
if(should_route?(packet, parts))
|
22
|
+
# Take parts of route and set packet info
|
23
|
+
packet['route.resource'] = parts[:resource] if parts[:resource]
|
24
|
+
packet['route.resource_id'] = parts[:resource_id] if parts[:resource_id]
|
25
|
+
packet['route.resource_action'] = parts[:resource_action] if parts[:resource_action]
|
26
|
+
|
27
|
+
# Take remainder and set to resource_path
|
28
|
+
packet['route.resource_path'] = parts[:remainder]
|
29
|
+
|
30
|
+
# Set self as router if resource was found
|
31
|
+
if(packet['route.resource', false])
|
32
|
+
packet['route.router'] = self
|
33
|
+
elsif(@not_found)
|
34
|
+
packet['route.resource'] = @not_found
|
35
|
+
packet['route.router'] = self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
pass packet
|
40
|
+
end
|
41
|
+
|
42
|
+
def route_parts(packet)
|
43
|
+
return_parts = {}
|
44
|
+
path = packet['route.path'] || packet.request.path_info
|
45
|
+
parts = path.split('/')
|
46
|
+
pad = parts.shift
|
47
|
+
if !parts.empty?
|
48
|
+
resource = parts.shift
|
49
|
+
if orange.loaded?(resource.to_sym)
|
50
|
+
return_parts[:resource] = resource.to_sym
|
51
|
+
if !parts.empty?
|
52
|
+
second = parts.shift
|
53
|
+
if second =~ /^\d+$/
|
54
|
+
return_parts[:resource_id] = second
|
55
|
+
if !parts.empty?
|
56
|
+
return_parts[:resource_action] = parts.shift.to_sym
|
57
|
+
else
|
58
|
+
return_parts[:resource_action] = :show
|
59
|
+
end
|
60
|
+
else
|
61
|
+
return_parts[:resource_action] = second.to_sym
|
62
|
+
end
|
63
|
+
else
|
64
|
+
return_parts[:resource_action] = :list
|
65
|
+
end # end check for second part
|
66
|
+
else
|
67
|
+
parts.unshift(resource)
|
68
|
+
end # end check for loaded resource
|
69
|
+
end # end check for nonempty route
|
70
|
+
return_parts[:remainder] = parts.unshift(pad).join('/')
|
71
|
+
return_parts
|
72
|
+
end
|
73
|
+
|
74
|
+
def should_route?(packet, parts)
|
75
|
+
return false unless @exposed.has_key?(packet['route.context'])
|
76
|
+
action_exposed?(@exposed[packet['route.context']], parts)
|
77
|
+
end
|
78
|
+
|
79
|
+
def action_exposed?(list, route_parts)
|
80
|
+
return true if list == :all
|
81
|
+
return true if list == route_parts[:resource_action]
|
82
|
+
return true if list.is_a?(Array) && list.include?(route_parts[:resource_action])
|
83
|
+
if list.is_a?(Hash)
|
84
|
+
all = list.has_key?(:all) ? action_exposed?(list[:all], route_parts) : false
|
85
|
+
one = list.has_key?(route_parts[:resource]) ? action_exposed?(list[route_parts[:resource]], route_parts) : false
|
86
|
+
return all || one
|
87
|
+
end
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
def route(packet)
|
92
|
+
resource = packet['route.resource']
|
93
|
+
raise 'resource not found' unless orange.loaded? resource
|
94
|
+
mode = packet['route.resource_action'] ||
|
95
|
+
(packet['route.resource_id'] ? :show : :list)
|
96
|
+
packet[:content] = orange[resource].view packet
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
|
3
|
+
module Orange::Middleware
|
4
|
+
# This middleware handles setting orange.env['route.context']
|
5
|
+
# to a value based on the route, if any. The route is then
|
6
|
+
# trimmed before continuing on.
|
7
|
+
class RouteContext < Base
|
8
|
+
def initialize(app, core, *args)
|
9
|
+
opts = args.extract_options!
|
10
|
+
opts.with_defaults!(:contexts => [:preview, :live, :admin, :orange],
|
11
|
+
:default => :live,
|
12
|
+
:urls => {})
|
13
|
+
@app = app
|
14
|
+
@core = core
|
15
|
+
@contexts = opts[:contexts]
|
16
|
+
@default = opts[:default]
|
17
|
+
@urls = opts[:urls]
|
18
|
+
end
|
19
|
+
def packet_call(packet)
|
20
|
+
path_info = packet['route.path'] || packet.env['PATH_INFO']
|
21
|
+
path = path_info.split('/')
|
22
|
+
pad = path.shift # Shift off empty first part
|
23
|
+
if @urls[packet.request.host]
|
24
|
+
packet['route.context'] = urls[packet.request.host]
|
25
|
+
elsif path.empty?
|
26
|
+
packet['route.context'] = @default
|
27
|
+
else
|
28
|
+
if(@contexts.include?(path.first.to_sym))
|
29
|
+
packet['route.context'] = path.shift.to_sym
|
30
|
+
path.unshift(pad)
|
31
|
+
packet['route.path'] = path.join('/')
|
32
|
+
else
|
33
|
+
packet['route.context'] = @default
|
34
|
+
end
|
35
|
+
end
|
36
|
+
pass packet
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'orange-core/middleware/base'
|
2
|
+
|
3
|
+
module Orange::Middleware
|
4
|
+
# This middleware handles setting orange.env['route.site_url']
|
5
|
+
# to a value based on the route, if any. The route is then
|
6
|
+
# trimmed before continuing on.
|
7
|
+
#
|
8
|
+
# Options -
|
9
|
+
# :multi - does Orange need to handle multiple urls
|
10
|
+
# :fake_it - host url(s) that Orange will fake requests on
|
11
|
+
# ex: :multi => true, :fake_it => 'localhost'
|
12
|
+
# will fake hostnames as first component of url
|
13
|
+
# only on localhost
|
14
|
+
class RouteSite < Base
|
15
|
+
def initialize(app, core, *args)
|
16
|
+
opts = args.extract_options!
|
17
|
+
opts.with_defaults!(:multi => false, :fake_it => ['localhost'])
|
18
|
+
@app = app
|
19
|
+
@core = core
|
20
|
+
@multi = opts[:multi]
|
21
|
+
# Put fake_it into an array, if necessary
|
22
|
+
@fake_it = opts[:fake_it].respond_to?(:include?) ?
|
23
|
+
opts[:fake_it] : [opts[:fake_it]]
|
24
|
+
end
|
25
|
+
|
26
|
+
def packet_call(packet)
|
27
|
+
request = packet.request
|
28
|
+
path_info = packet['route.path'] || packet.env['PATH_INFO']
|
29
|
+
path = path_info.split('/')
|
30
|
+
pad = path.shift # Shift off empty first part
|
31
|
+
packet['route.faked_site'] = false
|
32
|
+
if @multi
|
33
|
+
if path.empty?
|
34
|
+
packet['route.site_url'] = request.host
|
35
|
+
else
|
36
|
+
if @fake_it.include?(request.host)
|
37
|
+
packet['route.site_url'] = path.shift
|
38
|
+
packet['route.faked_site'] = true
|
39
|
+
else
|
40
|
+
packet['route.site_url'] = request.host
|
41
|
+
end
|
42
|
+
path.unshift(pad)
|
43
|
+
packet['route.path'] = path.join('/')
|
44
|
+
end
|
45
|
+
else
|
46
|
+
packet['route.site_url'] = request.host
|
47
|
+
end
|
48
|
+
pass packet
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|