nitro 0.31.0 → 0.40.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/nitro +135 -37
- data/doc/CHANGELOG.1 +108 -108
- data/doc/CHANGELOG.2 +89 -89
- data/doc/CHANGELOG.3 +105 -105
- data/{CHANGELOG → doc/CHANGELOG.4} +509 -509
- data/doc/{AUTHORS → CONTRIBUTORS} +49 -37
- data/doc/LIBRARIES +13 -0
- data/doc/LICENSE +2 -3
- data/doc/MIGRATION +45 -0
- data/doc/RELEASES +131 -11
- data/doc/TODO +67 -0
- data/lib/glue/magick.rb +0 -3
- data/lib/glue/sweeper.rb +30 -15
- data/lib/glue/thumbnails.rb +0 -2
- data/lib/glue/webfile.rb +23 -11
- data/lib/nitro.rb +37 -44
- data/lib/nitro/adapter/cgi.rb +0 -3
- data/lib/nitro/adapter/console.rb +0 -2
- data/lib/nitro/adapter/fastcgi.rb +6 -3
- data/lib/nitro/adapter/mongrel.rb +97 -58
- data/lib/nitro/adapter/script.rb +4 -6
- data/lib/nitro/adapter/webrick.rb +33 -87
- data/lib/nitro/adapter/webrick/vcr.rb +85 -0
- data/lib/nitro/caching.rb +0 -2
- data/lib/nitro/caching/actions.rb +0 -2
- data/lib/nitro/caching/fragments.rb +0 -2
- data/lib/nitro/caching/output.rb +45 -16
- data/lib/nitro/caching/proxy.rb +49 -0
- data/lib/nitro/cgi.rb +3 -6
- data/lib/nitro/cgi/cookie.rb +0 -3
- data/lib/nitro/cgi/request.rb +67 -24
- data/lib/nitro/cgi/response.rb +0 -2
- data/lib/nitro/cgi/{sendfile.rb → send_file.rb} +7 -6
- data/lib/nitro/compiler.rb +62 -55
- data/lib/nitro/compiler/cleanup.rb +0 -3
- data/lib/nitro/compiler/elements.rb +31 -28
- data/lib/nitro/compiler/errors.rb +2 -5
- data/lib/nitro/compiler/include.rb +10 -8
- data/lib/nitro/compiler/layout.rb +0 -2
- data/lib/nitro/compiler/localization.rb +0 -2
- data/lib/nitro/compiler/markup.rb +14 -6
- data/lib/nitro/compiler/morphing.rb +1 -5
- data/lib/nitro/compiler/script.rb +2 -4
- data/lib/nitro/compiler/squeeze.rb +0 -2
- data/lib/nitro/compiler/xslt.rb +0 -2
- data/lib/nitro/context.rb +10 -5
- data/lib/nitro/control.rb +18 -0
- data/lib/nitro/control/attribute.rb +88 -0
- data/lib/nitro/control/attribute/checkbox.rb +19 -0
- data/lib/nitro/control/attribute/datetime.rb +21 -0
- data/lib/nitro/control/attribute/file.rb +20 -0
- data/lib/nitro/control/attribute/fixnum.rb +26 -0
- data/lib/nitro/control/attribute/float.rb +26 -0
- data/lib/nitro/control/attribute/options.rb +38 -0
- data/lib/nitro/control/attribute/password.rb +16 -0
- data/lib/nitro/control/attribute/text.rb +16 -0
- data/lib/nitro/control/attribute/textarea.rb +16 -0
- data/lib/nitro/control/none.rb +16 -0
- data/lib/nitro/control/relation.rb +53 -0
- data/lib/nitro/control/relation/belongs_to.rb +0 -0
- data/lib/nitro/control/relation/has_many.rb +97 -0
- data/lib/nitro/control/relation/joins_many.rb +0 -0
- data/lib/nitro/control/relation/many_to_many.rb +0 -0
- data/lib/nitro/control/relation/refers_to.rb +29 -0
- data/lib/nitro/controller.rb +7 -296
- data/lib/nitro/dispatcher.rb +72 -34
- data/lib/nitro/element.rb +36 -10
- data/lib/nitro/element/javascript.rb +0 -2
- data/lib/nitro/flash.rb +23 -10
- data/lib/nitro/global.rb +36 -11
- data/lib/nitro/helper.rb +22 -8
- data/lib/nitro/helper/benchmark.rb +0 -2
- data/lib/nitro/helper/buffer.rb +0 -3
- data/lib/nitro/helper/css.rb +12 -0
- data/lib/nitro/helper/debug.rb +1 -3
- data/lib/nitro/helper/default.rb +1 -0
- data/lib/nitro/helper/feed.rb +400 -386
- data/lib/nitro/helper/form.rb +246 -116
- data/lib/nitro/helper/javascript.rb +28 -2
- data/lib/nitro/helper/javascript/morphing.rb +0 -2
- data/lib/nitro/helper/javascript/prototype.rb +0 -2
- data/lib/nitro/helper/javascript/scriptaculous.rb +0 -1
- data/lib/nitro/helper/layout.rb +0 -2
- data/lib/nitro/helper/navigation.rb +87 -0
- data/lib/nitro/helper/pager.rb +11 -22
- data/lib/nitro/helper/table.rb +9 -32
- data/lib/nitro/helper/url.rb +104 -0
- data/lib/nitro/helper/xhtml.rb +20 -4
- data/lib/nitro/helper/xml.rb +0 -2
- data/lib/nitro/markup.rb +131 -0
- data/lib/nitro/part.rb +52 -7
- data/lib/nitro/publishable.rb +328 -0
- data/lib/nitro/render.rb +30 -61
- data/lib/nitro/router.rb +12 -4
- data/lib/nitro/sanitize.rb +48 -0
- data/lib/nitro/scaffold.rb +9 -11
- data/lib/nitro/scaffold/controller.rb +25 -0
- data/lib/nitro/scaffold/model.rb +150 -0
- data/lib/nitro/scaffolding.rb +1 -3
- data/lib/nitro/server.rb +57 -32
- data/lib/nitro/server/drb.rb +16 -2
- data/lib/nitro/server/runner.rb +80 -102
- data/lib/nitro/service.rb +0 -1
- data/lib/nitro/service/xmlrpc.rb +0 -2
- data/lib/nitro/session.rb +26 -18
- data/lib/nitro/session/drb.rb +2 -16
- data/lib/nitro/session/memory.rb +0 -2
- data/lib/nitro/template.rb +219 -0
- data/lib/nitro/test/assertions.rb +1 -3
- data/lib/nitro/test/context.rb +0 -1
- data/lib/nitro/test/testcase.rb +0 -1
- data/lib/nitro/version.rb +6 -0
- data/lib/part/admin.rb +16 -0
- data/lib/part/admin/controller.rb +19 -0
- data/lib/part/admin/helper.rb +30 -0
- data/lib/part/admin/og/controller.rb +114 -0
- data/lib/part/admin/og/customize.rb +4 -0
- data/lib/part/admin/og/template/index.xhtml +27 -0
- data/lib/part/admin/og/template/list.xhtml +38 -0
- data/lib/part/admin/og/template/search.xhtml +20 -0
- data/lib/part/admin/og/template/update.xhtml +25 -0
- data/lib/part/admin/skin.rb +207 -0
- data/lib/part/admin/template/denied.xhtml +13 -0
- data/lib/part/admin/template/index.xhtml +12 -0
- data/lib/part/admin/todo.txt +2 -0
- data/proto/public/error.xhtml +4 -2
- data/proto/run.rb +0 -2
- data/test/glue/tc_webfile.rb +1 -0
- data/test/nitro/cgi/tc_request.rb +23 -0
- data/test/nitro/helper/tc_feed.rb +0 -3
- data/test/nitro/helper/tc_navbar.rb +74 -0
- data/test/nitro/helper/tc_table.rb +2 -0
- data/test/nitro/tc_cgi.rb +72 -19
- data/test/nitro/tc_controller.rb +35 -26
- data/test/nitro/tc_controller_aspect.rb +1 -0
- data/test/nitro/tc_controller_params.rb +864 -0
- data/test/nitro/tc_dispatcher.rb +2 -2
- data/test/nitro/tc_element.rb +16 -16
- data/test/nitro/tc_flash.rb +3 -3
- data/test/nitro/tc_markup.rb +31 -0
- data/test/nitro/tc_render.rb +12 -14
- data/test/nitro/tc_session.rb +9 -7
- data/test/nitro/tc_template.rb +34 -0
- metadata +217 -198
- data/INSTALL +0 -121
- data/ProjectInfo +0 -74
- data/README +0 -555
- data/doc/apache.txt +0 -9
- data/doc/config.txt +0 -28
- data/doc/faq.txt +0 -7
- data/doc/lhttpd.txt +0 -7
- data/lib/nitro/adapter/scgi.rb +0 -239
- data/lib/nitro/helper/form/builder.rb +0 -144
- data/lib/nitro/helper/form/controls.rb +0 -389
- data/lib/nitro/helper/rss.rb +0 -72
- data/proto/conf/apache.conf +0 -51
- data/proto/public/scaffold/advanced_search.xhtml +0 -30
- data/proto/public/scaffold/edit.xhtml +0 -11
- data/proto/public/scaffold/form.xhtml +0 -1
- data/proto/public/scaffold/index.xhtml +0 -20
- data/proto/public/scaffold/list.xhtml +0 -32
- data/proto/public/scaffold/new.xhtml +0 -11
- data/proto/public/scaffold/search.xhtml +0 -29
- data/proto/public/scaffold/view.xhtml +0 -8
- data/proto/script/scgi_ctl +0 -221
- data/proto/script/scgi_service +0 -128
- data/setup.rb +0 -1585
- data/src/part/admin.rb +0 -16
- data/src/part/admin/controller.rb +0 -81
- data/src/part/admin/skin.rb +0 -21
- data/src/part/admin/system.css +0 -135
- data/src/part/admin/template/denied.xhtml +0 -1
- data/src/part/admin/template/index.xhtml +0 -43
- data/test/nitro/helper/tc_rss.rb +0 -24
data/lib/glue/magick.rb
CHANGED
data/lib/glue/sweeper.rb
CHANGED
@@ -13,12 +13,22 @@ module Glue
|
|
13
13
|
|
14
14
|
module Sweeper
|
15
15
|
include Aspects
|
16
|
-
|
16
|
+
|
17
|
+
#--
|
18
|
+
# Inject the sweepers *after* the event to have a valid
|
19
|
+
# oid.
|
20
|
+
#++
|
21
|
+
|
17
22
|
before "sweep_affected(:insert)", :on => :og_insert
|
18
23
|
before "sweep_affected(:update)", :on => :og_update
|
19
24
|
before "sweep_affected(:delete)", :on => :og_delete
|
20
25
|
|
21
26
|
# Expires (deletes) a cached page from the file system.
|
27
|
+
#
|
28
|
+
# == Input
|
29
|
+
#
|
30
|
+
# * relative = if set to true, prepends the controller
|
31
|
+
# mount path.
|
22
32
|
#--
|
23
33
|
# FIXME: replace with 'extend Nitro::Caching::Output' ?
|
24
34
|
# this way we wont have to sync the same code in two different
|
@@ -27,14 +37,16 @@ module Sweeper
|
|
27
37
|
# expire method.
|
28
38
|
#++
|
29
39
|
|
30
|
-
def self.expire(name, klass)
|
31
|
-
|
32
|
-
filename = "#{Server.public_root}/#{
|
33
|
-
|
34
|
-
|
35
|
-
rescue Object
|
36
|
-
# gmosx: is this the right thing to do?
|
40
|
+
def self.expire(name, klass, relative = false)
|
41
|
+
if relative and controller = klass.ann.self[:controller]
|
42
|
+
filename = "#{Server.public_root}/#{controller.mount_path}/#{name}.html".squeeze('/')
|
43
|
+
else
|
44
|
+
filename = "#{Server.public_root}/#{name}.html".squeeze('/')
|
37
45
|
end
|
46
|
+
Logger.debug "Sweeper expired cache file '#{filename}'" if $DBG
|
47
|
+
FileUtils.rm_rf(filename)
|
48
|
+
rescue Object => ex
|
49
|
+
# ignore any error.
|
38
50
|
end
|
39
51
|
|
40
52
|
private
|
@@ -52,12 +64,17 @@ private
|
|
52
64
|
end
|
53
65
|
alias_method :expire_affected, :sweep_affected
|
54
66
|
|
55
|
-
|
56
|
-
# Generally you don't
|
57
|
-
|
67
|
+
# Called from an action that modifies the model to expire
|
68
|
+
# affected (dependend) cached pages. Generally you don't
|
69
|
+
# override this method.
|
70
|
+
#
|
71
|
+
# == Input
|
72
|
+
#
|
73
|
+
# * relative = if set to true, prepends the controller
|
74
|
+
# mount path.
|
58
75
|
|
59
|
-
def expire_affected_output(name)
|
60
|
-
Sweeper.expire(name, self.class)
|
76
|
+
def expire_affected_output(name, relative = true)
|
77
|
+
Sweeper.expire(name, self.class, relative)
|
61
78
|
end
|
62
79
|
alias_method :expire_output, :expire_affected_output
|
63
80
|
|
@@ -71,5 +88,3 @@ private
|
|
71
88
|
end
|
72
89
|
|
73
90
|
end
|
74
|
-
|
75
|
-
# * George Moschovitis <gm@navel.gr>
|
data/lib/glue/thumbnails.rb
CHANGED
data/lib/glue/webfile.rb
CHANGED
@@ -27,33 +27,45 @@ class WebFile
|
|
27
27
|
# webapp dir for easier updates.
|
28
28
|
|
29
29
|
setting :upload_root, :default => 'upload', :doc => 'The directory where upload files are stored'
|
30
|
+
|
31
|
+
# Override files by default?
|
32
|
+
|
33
|
+
setting :override_files, :default => true, :doc => 'Override files by default?'
|
30
34
|
|
31
35
|
# Modify the base class when this class is included as
|
32
36
|
# property
|
33
37
|
|
34
|
-
def self.included_as_property
|
38
|
+
def self.included_as_property base, args
|
39
|
+
if args.last.is_a?(Hash)
|
40
|
+
options = args.pop
|
41
|
+
else
|
42
|
+
options = Hash.new
|
43
|
+
end
|
44
|
+
|
45
|
+
args.pop if args.last.is_a?(Class)
|
46
|
+
|
35
47
|
if thumbnails = (options[:thumbnail] || options[:thumbnails] || options[:magick]) or self.name == 'WebImage'
|
36
48
|
require 'glue/thumbnails'
|
37
49
|
base.send :include, Thumbnails
|
38
50
|
thumbnails = { :small => :thumbnails } if thumbnails.is_a?(String)
|
39
51
|
end
|
40
52
|
|
41
|
-
for name in
|
53
|
+
for name in args
|
42
54
|
base.module_eval do
|
43
55
|
# The 'web' path to the file (relative to the public
|
44
56
|
# root directory. Uses the original property name
|
45
57
|
# or the #{name}_path alias.
|
46
58
|
|
47
|
-
|
59
|
+
attr_accessor name.to_sym, String
|
48
60
|
alias_method "#{name}_path".to_sym, name.to_sym
|
49
61
|
|
50
62
|
# The file size.
|
51
63
|
|
52
|
-
|
64
|
+
attr_accessor "#{name}_size".to_sym, Fixnum
|
53
65
|
|
54
|
-
# The mime type
|
66
|
+
# The mime type.
|
55
67
|
|
56
|
-
|
68
|
+
attr_accessor "#{name}_mime_type".to_sym, String
|
57
69
|
|
58
70
|
# Assignment callbacks.
|
59
71
|
#--
|
@@ -66,7 +78,7 @@ class WebFile
|
|
66
78
|
if thumbnails
|
67
79
|
for tname in thumbnails.keys
|
68
80
|
base.module_eval do
|
69
|
-
|
81
|
+
attr_accessor "#{name}_#{tname}_thumbnail".to_sym, String
|
70
82
|
end
|
71
83
|
end
|
72
84
|
end
|
@@ -78,6 +90,8 @@ class WebFile
|
|
78
90
|
|
79
91
|
def #{name}_from_request(request)
|
80
92
|
param = request['#{name}']
|
93
|
+
|
94
|
+
return if param.nil? or param.original_filename.blank?
|
81
95
|
}
|
82
96
|
if base.respond_to? :webfile_path
|
83
97
|
code << %{
|
@@ -94,6 +108,7 @@ class WebFile
|
|
94
108
|
@#{name}_size = param.size
|
95
109
|
|
96
110
|
real_path = #{name}_real_path
|
111
|
+
raise 'file exists' if !WebFile.override_files and File.exists?(real_path)
|
97
112
|
FileUtils.mkdir_p(File.dirname(real_path))
|
98
113
|
if param.path
|
99
114
|
FileUtils.cp(param.path, real_path)
|
@@ -102,7 +117,7 @@ class WebFile
|
|
102
117
|
param.rewind
|
103
118
|
File.open(real_path, 'wb') { |f| f << param.read }
|
104
119
|
end
|
105
|
-
FileUtils.chmod(
|
120
|
+
FileUtils.chmod(0664, real_path)
|
106
121
|
}
|
107
122
|
|
108
123
|
if thumbnails
|
@@ -145,6 +160,3 @@ end
|
|
145
160
|
WebImage = WebFile
|
146
161
|
|
147
162
|
end
|
148
|
-
|
149
|
-
# * George Moschovitis <gm@navel.gr>
|
150
|
-
# * Michael Fellinger <m.fellinger@gmail.com>
|
data/lib/nitro.rb
CHANGED
@@ -1,23 +1,19 @@
|
|
1
1
|
# = Nitro
|
2
2
|
#
|
3
3
|
# Copyright (c) 2004-2006, George Moschovitis (http://www.gmosx.com)
|
4
|
-
# Copyright (c) 2004-2006, Navel Ltd (http://www.navel.gr)
|
5
4
|
#
|
6
5
|
# Nitro (http://www.nitroproject.org) is copyrighted free software
|
7
|
-
# created and maintained by George Moschovitis
|
8
|
-
# and released under the
|
9
|
-
# consult the file doc/LICENCE.
|
6
|
+
# created and maintained by George Moschovitis
|
7
|
+
# (mailto:george.moschovitis@gmail.com) and released under the
|
8
|
+
# standard BSD Licence. For details consult the file doc/LICENCE.
|
10
9
|
|
11
10
|
require 'glue'
|
12
11
|
require 'glue/logger'
|
13
12
|
require 'glue/configuration'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
# The version.
|
18
|
-
|
19
|
-
Version = '0.31.0'
|
14
|
+
require 'nitro/version'
|
20
15
|
|
16
|
+
module Nitro
|
21
17
|
# Library path.
|
22
18
|
|
23
19
|
LibPath = File.dirname(__FILE__)
|
@@ -26,15 +22,32 @@ module Nitro
|
|
26
22
|
|
27
23
|
setting :proto_path, :default => File.join(LibPath, '..', 'proto'), :doc => 'The path to the prototype application'
|
28
24
|
|
29
|
-
#
|
30
|
-
|
31
|
-
$LOAD_PATH.unshift File.join(LibPath, '..', 'src')
|
25
|
+
# The adapter used to serve nitro applications.
|
32
26
|
|
33
|
-
|
27
|
+
setting :adapter, :default => :webrick, :doc => 'The web adapter'
|
28
|
+
|
29
|
+
# Add standard dirs in the path.
|
30
|
+
|
31
|
+
$LOAD_PATH.unshift Dir.pwd
|
32
|
+
$LOAD_PATH.unshift File.join(Dir.pwd, 'lib')
|
33
|
+
|
34
|
+
# Include the Glue namespace in Nitro.
|
34
35
|
|
35
36
|
include Glue
|
36
37
|
end
|
37
38
|
|
39
|
+
#--
|
40
|
+
# gmosx: leave them here.
|
41
|
+
#++
|
42
|
+
|
43
|
+
require 'nitro/global'
|
44
|
+
require 'nitro/context'
|
45
|
+
require 'nitro/controller'
|
46
|
+
require 'nitro/dispatcher'
|
47
|
+
require 'nitro/render'
|
48
|
+
require 'nitro/server'
|
49
|
+
require 'nitro/part'
|
50
|
+
|
38
51
|
unless $NITRO_NO_ENVIRONMENT
|
39
52
|
# Setup up the proposed environment. You are free
|
40
53
|
# to skip this if you dont like it. Just set
|
@@ -47,58 +60,38 @@ unless $NITRO_NO_ENVIRONMENT
|
|
47
60
|
|
48
61
|
Dir.chdir(File.dirname($0))
|
49
62
|
|
50
|
-
# Application code come here.
|
51
|
-
|
52
|
-
$LOAD_PATH.unshift 'src'
|
53
|
-
|
54
63
|
# Library code come here.
|
55
64
|
|
56
65
|
$LOAD_PATH.unshift 'lib'
|
57
66
|
end
|
58
67
|
|
59
|
-
#--
|
60
|
-
# gmosx: leave them here.
|
61
|
-
#++
|
62
|
-
|
63
|
-
require 'nitro/global'
|
64
|
-
require 'nitro/context'
|
65
|
-
require 'nitro/controller'
|
66
|
-
require 'nitro/dispatcher'
|
67
|
-
require 'nitro/render'
|
68
|
-
require 'nitro/server'
|
69
|
-
require 'nitro/part'
|
70
|
-
|
71
68
|
module Nitro
|
72
69
|
|
73
70
|
class << self
|
74
71
|
|
72
|
+
attr_accessor :server
|
73
|
+
|
75
74
|
# A helper method to start a Nitro application.
|
76
75
|
|
77
76
|
def run(controller = nil)
|
78
|
-
Server.run(controller)
|
77
|
+
@server = Server.run(controller)
|
79
78
|
end
|
80
79
|
alias_method :start, :run
|
81
80
|
|
82
|
-
# A helper
|
81
|
+
# A helper method. Will be deprecated, use
|
82
|
+
# Configuration.mode instead.
|
83
83
|
|
84
|
-
def
|
85
|
-
|
84
|
+
def live?
|
85
|
+
Configuration.mode == :live
|
86
86
|
end
|
87
|
-
alias_method :
|
88
|
-
|
87
|
+
alias_method :production?, :live?
|
89
88
|
|
90
|
-
#
|
89
|
+
# Deprecated, use Configuration.mode instead.
|
91
90
|
|
92
|
-
def
|
93
|
-
|
91
|
+
def mode
|
92
|
+
Configuration.mode
|
94
93
|
end
|
95
|
-
alias_method :production?, :live?
|
96
94
|
|
97
95
|
end
|
98
96
|
|
99
|
-
$global = $application = Global
|
100
|
-
|
101
97
|
end
|
102
|
-
|
103
|
-
|
104
|
-
# * George Moschovitis <gm@navel.gr>
|
data/lib/nitro/adapter/cgi.rb
CHANGED
@@ -22,10 +22,15 @@ module Nitro
|
|
22
22
|
#
|
23
23
|
# === Sessions
|
24
24
|
#
|
25
|
-
# As FCGI is process based, you have
|
25
|
+
# As FCGI is process based, you have can't use the default
|
26
26
|
# in-memory session store. For production web sites you should
|
27
27
|
# use the drb session store. Moreover, there is no need for
|
28
28
|
# DB connection pooling in Og.
|
29
|
+
#
|
30
|
+
#--
|
31
|
+
# gmosx: I always thought that the concept of FastCGI is stupid!
|
32
|
+
# Why don't you use a proxy setup? (For example Apache + Mongrel)
|
33
|
+
#++
|
29
34
|
|
30
35
|
class FastCGI
|
31
36
|
|
@@ -41,5 +46,3 @@ class FastCGI
|
|
41
46
|
end
|
42
47
|
|
43
48
|
end
|
44
|
-
|
45
|
-
# * George Moschovitis <gm@navel.gr>
|
@@ -16,6 +16,7 @@ Socket.do_not_reverse_lookup = true
|
|
16
16
|
#++
|
17
17
|
|
18
18
|
module Mongrel # :nodoc: all
|
19
|
+
|
19
20
|
class HttpRequest
|
20
21
|
def method_missing(name, *args)
|
21
22
|
if @params.has_key?(name.to_s.upcase)
|
@@ -27,6 +28,13 @@ module Mongrel # :nodoc: all
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
31
|
+
|
32
|
+
class Configurator
|
33
|
+
def log(msg)
|
34
|
+
Logger.info msg
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
30
38
|
end
|
31
39
|
|
32
40
|
module Nitro
|
@@ -35,57 +43,53 @@ class Mongrel
|
|
35
43
|
|
36
44
|
class << self
|
37
45
|
attr_accessor :mongrel
|
46
|
+
attr_accessor :mongrel_config
|
38
47
|
|
39
|
-
# Start the
|
48
|
+
# Start the Mongrel adapter.
|
40
49
|
|
41
50
|
def start(server)
|
42
51
|
# TODO add logging.
|
43
|
-
|
44
|
-
mongrel_options = server.options.dup
|
45
|
-
|
46
|
-
mongrel_options.update(
|
47
|
-
:BindAddress => server.address,
|
48
|
-
:Port => server.port,
|
49
|
-
:DocumentRoot => server.public_root
|
50
|
-
)
|
51
|
-
|
52
|
-
@mongrel = ::Mongrel::HttpServer.new(mongrel_options[:BindAddress],
|
53
|
-
mongrel_options[:Port])
|
54
|
-
|
55
|
-
trap('INT') { exit } # works until you use breakpoint... why?
|
56
|
-
|
57
|
-
@mongrel.register('/', MongrelAdapter.new(server))
|
58
|
-
|
59
|
-
initialize_mongrel(server)
|
60
|
-
|
61
|
-
@mongrel.run
|
62
|
-
@mongrel_thread = @mongrel.acceptor
|
63
|
-
@mongrel_thread.join
|
64
|
-
end
|
65
52
|
|
66
|
-
|
53
|
+
@mongrel_config = ::Mongrel::Configurator.new :host => server.address do
|
54
|
+
listener :port => server.port do
|
55
|
+
uri "/", :handler => MongrelAdapter.new(server)
|
56
|
+
trap('INT') { Nitro::Mongrel.stop(server) }
|
57
|
+
run
|
58
|
+
end
|
59
|
+
end
|
67
60
|
|
68
|
-
|
69
|
-
@
|
61
|
+
@mongrel_config.log("Started Mongrel on " + server.address + ":" + server.port.to_s)
|
62
|
+
@mongrel_config.join
|
70
63
|
end
|
71
|
-
|
64
|
+
|
65
|
+
# Stop the Mongrel adapter.
|
66
|
+
|
67
|
+
def stop(server = nil)
|
68
|
+
@mongrel_config.log("Stopped Mongrel on " + server.address + ":" + server.port.to_s)
|
69
|
+
@mongrel_config.stop
|
70
|
+
end
|
71
|
+
|
72
72
|
# Override this method to perform customized mongrel
|
73
73
|
# initialization.
|
74
|
-
|
74
|
+
|
75
75
|
def initialize_mongrel(server)
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
end
|
81
81
|
|
82
|
-
# A Mongrel Adapter for Nitro.
|
82
|
+
# A Mongrel Adapter for Nitro. This is the prefered adapter to
|
83
|
+
# use in production mode. Typically you will have a front-end
|
84
|
+
# web server (for example apache) handle static content and
|
85
|
+
# proxy dynamic content request to a cluster of mongrel servers.
|
83
86
|
|
84
87
|
class MongrelAdapter < ::Mongrel::HttpHandler
|
85
88
|
attr_accessor :server
|
86
|
-
|
89
|
+
|
87
90
|
def initialize(server)
|
88
91
|
@server = server
|
92
|
+
@handle_static_files = Server.handle_static_files
|
89
93
|
end
|
90
94
|
|
91
95
|
def process(req, res)
|
@@ -95,30 +99,45 @@ class MongrelAdapter < ::Mongrel::HttpHandler
|
|
95
99
|
# Handle a static file. Also handles cached pages.
|
96
100
|
|
97
101
|
def handle_file(req, res)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
rescue Object => ex
|
102
|
+
rewrite(req)
|
103
|
+
|
104
|
+
# gmosx, FIXME: this is a nasty hack that fixes a really
|
105
|
+
# *nasty* caching bug. Find a better solution. When hitting
|
106
|
+
# the backend server, if the index method takes parameters
|
107
|
+
# the dispatcher considers all static files as parameters.
|
108
|
+
# If you have output caching enabled for the index page,
|
109
|
+
# all your static files get corrupted.
|
110
|
+
|
111
|
+
if (@handle_static_files == false) and (req.path_info =~ /\.html$/)
|
109
112
|
return false
|
110
|
-
ensure
|
111
|
-
unrewrite(req)
|
112
113
|
end
|
114
|
+
|
115
|
+
# TODO: handle If-Modified-Since and add Last-Modified headers
|
116
|
+
|
117
|
+
filename = File.join(@server.public_root, req.path_info).squeeze('/')
|
118
|
+
|
119
|
+
File.open(filename, "rb") do |f|
|
120
|
+
# TODO: check whether path circumvents public_root directory?
|
121
|
+
res.status = 200
|
122
|
+
res.body << f.read # XXX inefficient for large files, may cause leaks
|
123
|
+
end
|
124
|
+
return true
|
125
|
+
rescue Errno::ENOENT => ex # TODO: Lookup Win32 error for 'file missing'
|
126
|
+
return false
|
127
|
+
ensure
|
128
|
+
unrewrite(req)
|
113
129
|
end
|
114
130
|
|
115
131
|
# Handle the request.
|
116
|
-
|
132
|
+
#--
|
133
|
+
# TODO: recode this like the camping mongrel handler.
|
134
|
+
#++
|
135
|
+
|
117
136
|
def handle(req, res)
|
118
137
|
unless handle_file(req, res)
|
119
|
-
path = req.path_info
|
120
|
-
|
121
138
|
begin
|
139
|
+
path = req.path_info
|
140
|
+
|
122
141
|
context = Context.new(@server)
|
123
142
|
|
124
143
|
context.in = if req.body.is_a? String
|
@@ -134,29 +153,52 @@ class MongrelAdapter < ::Mongrel::HttpHandler
|
|
134
153
|
end
|
135
154
|
context.headers[h] = v
|
136
155
|
}
|
156
|
+
|
157
|
+
# hackfix: make it behave like webrick and fcgi
|
158
|
+
context.headers['REQUEST_URI'] << "?#{context.headers['QUERY_STRING']}" if context.headers['QUERY_STRING']
|
159
|
+
context.headers['QUERY_STRING'] ||= ''
|
137
160
|
|
138
161
|
Cgi.parse_params(context)
|
139
162
|
Cgi.parse_cookies(context)
|
140
163
|
|
141
164
|
context.render(path)
|
165
|
+
=begin
|
166
|
+
res.start(context.status,true) do |head,out|
|
167
|
+
out.write(Cgi.response_headers(context))
|
168
|
+
out.write(context.out)
|
169
|
+
end
|
170
|
+
=end
|
171
|
+
|
172
|
+
# what is the error code if a request without a handler
|
173
|
+
# is comming?! al 2006-Aug-05
|
142
174
|
|
143
|
-
res.status
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
175
|
+
res.start(context.status, true) do |head,out|
|
176
|
+
context.response_headers.each do |key, value|
|
177
|
+
head[key] = value
|
178
|
+
end
|
179
|
+
|
180
|
+
context.response_cookies.each do |cookie|
|
181
|
+
head['Set-Cookie'] = cookie
|
182
|
+
end if context.response_cookies
|
183
|
+
|
184
|
+
out.write(context.out)
|
185
|
+
end
|
186
|
+
|
148
187
|
context.close
|
149
188
|
ensure
|
189
|
+
$autoreload_dirty = false
|
150
190
|
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager
|
151
191
|
end
|
152
192
|
end
|
153
193
|
end
|
154
194
|
|
195
|
+
# Try to rewrite the path to a filename.
|
196
|
+
|
155
197
|
def rewrite(req)
|
156
198
|
if req.path_info == '/' || req.path_info == ''
|
157
199
|
req.path_info = '/index.html'
|
158
200
|
elsif req.path_info =~ /^([^.]+)$/
|
159
|
-
req.path_info = "#{$1}
|
201
|
+
req.path_info = "#{$1}.html"
|
160
202
|
end
|
161
203
|
end
|
162
204
|
|
@@ -165,13 +207,10 @@ class MongrelAdapter < ::Mongrel::HttpHandler
|
|
165
207
|
def unrewrite(req)
|
166
208
|
if req.path_info == '/index.html'
|
167
209
|
req.path_info = '/'
|
168
|
-
elsif req.path_info =~ /^([^.]+)
|
210
|
+
elsif req.path_info =~ /^([^.]+)\.html$/
|
169
211
|
req.path_info = $1
|
170
212
|
end
|
171
213
|
end
|
172
214
|
end
|
173
215
|
|
174
216
|
end
|
175
|
-
|
176
|
-
# * Joshua Hoke
|
177
|
-
# * George Moschovitis <gm@navel.gr>
|