nitro 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +752 -543
- data/INSTALL +38 -38
- data/README +264 -225
- data/Rakefile +48 -49
- data/bin/nitro +3 -3
- data/bin/nitrogen +6 -6
- data/doc/AUTHORS +10 -10
- data/doc/CHANGELOG.1 +1939 -1939
- data/doc/CHANGELOG.2 +954 -954
- data/doc/LICENSE +3 -3
- data/doc/MIGRATION +28 -0
- data/doc/RELEASES +814 -643
- data/doc/config.txt +5 -5
- data/install.rb +7 -17
- data/lib/nitro.rb +38 -9
- data/lib/nitro/adapter/cgi.rb +311 -312
- data/lib/nitro/adapter/fastcgi.rb +18 -25
- data/lib/nitro/adapter/webrick.rb +128 -137
- data/lib/nitro/adapter/wee.rb +51 -0
- data/lib/nitro/caching.rb +20 -20
- data/lib/nitro/caching/actions.rb +43 -43
- data/lib/nitro/caching/fragments.rb +46 -46
- data/lib/nitro/caching/invalidation.rb +11 -11
- data/lib/nitro/caching/output.rb +65 -65
- data/lib/nitro/caching/stores.rb +67 -67
- data/lib/nitro/compiler.rb +262 -0
- data/lib/nitro/compiler/elements.rb +0 -0
- data/lib/nitro/compiler/errors.rb +65 -0
- data/lib/nitro/compiler/localization.rb +25 -0
- data/lib/nitro/compiler/markup.rb +19 -0
- data/lib/nitro/compiler/shaders.rb +206 -0
- data/lib/nitro/compiler/squeeze.rb +20 -0
- data/lib/nitro/compiler/xslt.rb +61 -0
- data/lib/nitro/context.rb +87 -88
- data/lib/nitro/controller.rb +151 -158
- data/lib/nitro/cookie.rb +34 -34
- data/lib/nitro/dispatcher.rb +195 -186
- data/lib/nitro/element.rb +132 -126
- data/lib/nitro/element/java_script.rb +6 -6
- data/lib/nitro/flash.rb +66 -66
- data/lib/nitro/mail.rb +192 -192
- data/lib/nitro/mixin/buffer.rb +66 -0
- data/lib/nitro/mixin/debug.rb +16 -16
- data/lib/nitro/mixin/form.rb +88 -0
- data/lib/nitro/mixin/helper.rb +2 -2
- data/lib/nitro/mixin/javascript.rb +108 -108
- data/lib/nitro/mixin/markup.rb +144 -0
- data/lib/nitro/mixin/pager.rb +202 -202
- data/lib/nitro/mixin/rss.rb +67 -0
- data/lib/nitro/mixin/table.rb +63 -0
- data/lib/nitro/mixin/xhtml.rb +75 -0
- data/lib/nitro/mixin/xml.rb +124 -0
- data/lib/nitro/render.rb +183 -359
- data/lib/nitro/request.rb +140 -140
- data/lib/nitro/response.rb +27 -27
- data/lib/nitro/routing.rb +21 -21
- data/lib/nitro/scaffold.rb +124 -118
- data/lib/nitro/server.rb +117 -80
- data/lib/nitro/server/runner.rb +341 -0
- data/lib/nitro/service.rb +12 -12
- data/lib/nitro/service/xmlrpc.rb +22 -22
- data/lib/nitro/session.rb +122 -120
- data/lib/nitro/session/drb.rb +9 -9
- data/lib/nitro/session/drbserver.rb +34 -34
- data/lib/nitro/template.rb +171 -155
- data/lib/nitro/testing/assertions.rb +90 -90
- data/lib/nitro/testing/context.rb +16 -16
- data/lib/nitro/testing/testcase.rb +34 -34
- data/proto/conf/lhttpd.conf +9 -9
- data/proto/public/error.xhtml +75 -75
- data/proto/public/index.xhtml +18 -18
- data/proto/public/js/behaviour.js +65 -65
- data/proto/public/js/controls.js +1 -1
- data/proto/public/js/prototype.js +3 -3
- data/proto/public/settings.xhtml +61 -61
- data/proto/run.rb +1 -5
- data/test/nitro/adapter/raw_post1.bin +0 -0
- data/test/nitro/adapter/tc_cgi.rb +57 -57
- data/test/nitro/adapter/tc_webrick.rb +4 -4
- data/test/nitro/mixin/tc_pager.rb +25 -25
- data/test/nitro/mixin/tc_rss.rb +24 -0
- data/test/nitro/mixin/tc_table.rb +31 -0
- data/test/nitro/mixin/tc_xhtml.rb +13 -0
- data/test/nitro/tc_caching.rb +10 -10
- data/test/nitro/tc_context.rb +8 -8
- data/test/nitro/tc_controller.rb +48 -48
- data/test/nitro/tc_cookie.rb +6 -6
- data/test/nitro/tc_dispatcher.rb +64 -64
- data/test/nitro/tc_element.rb +27 -27
- data/test/nitro/tc_flash.rb +31 -31
- data/test/nitro/tc_mail.rb +63 -63
- data/test/nitro/tc_server.rb +26 -26
- data/test/nitro/tc_session.rb +9 -9
- data/test/nitro/tc_template.rb +19 -19
- data/test/public/blog/list.xhtml +1 -1
- metadata +31 -37
- data/lib/nitro/buffering.rb +0 -45
- data/lib/nitro/builder/form.rb +0 -104
- data/lib/nitro/builder/rss.rb +0 -104
- data/lib/nitro/builder/table.rb +0 -80
- data/lib/nitro/builder/xhtml.rb +0 -132
- data/lib/nitro/builder/xml.rb +0 -131
- data/lib/nitro/conf.rb +0 -36
- data/lib/nitro/environment.rb +0 -21
- data/lib/nitro/errors.rb +0 -69
- data/lib/nitro/localization.rb +0 -153
- data/lib/nitro/markup.rb +0 -147
- data/lib/nitro/output.rb +0 -24
- data/lib/nitro/runner.rb +0 -348
- data/lib/nitro/shaders.rb +0 -206
- data/test/nitro/builder/tc_rss.rb +0 -23
- data/test/nitro/builder/tc_table.rb +0 -30
- data/test/nitro/builder/tc_xhtml.rb +0 -39
- data/test/nitro/builder/tc_xml.rb +0 -56
- data/test/nitro/tc_localization.rb +0 -49
@@ -17,38 +17,31 @@ module Nitro
|
|
17
17
|
# scalable, open extension to CGI that provides high
|
18
18
|
# performance without the limitations of server
|
19
19
|
# specific APIs.
|
20
|
+
#
|
21
|
+
# No need for connection pooling, fastcgi uses processes.
|
20
22
|
|
21
23
|
class FastCGI
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
begin
|
28
|
-
context = Context.new(conf)
|
25
|
+
def self.start(server)
|
26
|
+
FCGI.each do |cgi|
|
27
|
+
begin
|
28
|
+
context = Context.new(server)
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
context.in = cgi.in
|
31
|
+
context.headers = cgi.env
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
# Og.db.get_connection if defined?(Og) and Og.db
|
33
|
+
CgiUtils.parse_params(context)
|
34
|
+
CgiUtils.parse_cookies(context)
|
35
|
+
|
36
|
+
context.render(context.path)
|
38
37
|
|
39
|
-
|
38
|
+
cgi.out.print(CgiUtils.response_headers(context))
|
39
|
+
cgi.out.print(context.out)
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
cgi.finish
|
47
|
-
ensure
|
48
|
-
# Og.db.put_connection if defined?(Og) and Og.db
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
41
|
+
cgi.finish
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
52
45
|
|
53
46
|
end
|
54
47
|
|
@@ -8,161 +8,152 @@ require 'nitro/dispatcher'
|
|
8
8
|
# Speeds things up, more comaptible with OSX.
|
9
9
|
|
10
10
|
Socket.do_not_reverse_lookup = true
|
11
|
-
|
11
|
+
|
12
12
|
module Nitro
|
13
|
-
|
13
|
+
|
14
14
|
# Helper methods for the WebrickAdapter.
|
15
15
|
|
16
16
|
class Webrick
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
trap('INT') { @server.shutdown }
|
46
|
-
|
47
|
-
@server.mount('/', WebrickAdapter, conf)
|
48
|
-
@server.start
|
49
|
-
end
|
50
|
-
end
|
18
|
+
class << self
|
19
|
+
attr_accessor :webrick
|
20
|
+
|
21
|
+
def start(server)
|
22
|
+
if RUBY_PLATFORM !~ /mswin32/
|
23
|
+
wblog = WEBrick::BasicLog::new('/dev/null')
|
24
|
+
elsif server.access_log
|
25
|
+
wblog = WEBrick::BasicLog::new(server.access_log || 'log/access.log')
|
26
|
+
else
|
27
|
+
wblog = STDERR
|
28
|
+
end
|
29
|
+
@webrick = WEBrick::HTTPServer.new(
|
30
|
+
:BindAddress => server.address,
|
31
|
+
:Port => server.port,
|
32
|
+
:DocumentRoot => server.public_root,
|
33
|
+
:AccessLog => [
|
34
|
+
[wblog, WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
35
|
+
[wblog, WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
36
|
+
]
|
37
|
+
)
|
38
|
+
|
39
|
+
trap('INT') { @webrick.shutdown }
|
40
|
+
|
41
|
+
@webrick.mount('/', WebrickAdapter, server)
|
42
|
+
@webrick.start
|
43
|
+
end
|
44
|
+
end
|
51
45
|
|
52
46
|
end
|
53
47
|
|
54
48
|
# A special handler for Xhtml files.
|
55
49
|
|
56
50
|
class XhtmlFileHandler < WEBrick::HTTPServlet::DefaultFileHandler
|
57
|
-
|
51
|
+
def do_GET(req, res)
|
58
52
|
res['content-type'] = 'text/html'
|
59
53
|
res.body = '<html><body>Permission denied</body></html>'
|
60
|
-
|
54
|
+
end
|
61
55
|
end
|
62
56
|
|
63
57
|
# A Webrick Adapter for Nitro.
|
64
|
-
#--
|
65
|
-
# TODO: optimize the conversion from WEBrick's
|
66
|
-
# parameters to the Nitro parameters.
|
67
|
-
#++
|
68
58
|
|
69
59
|
class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
60
|
+
include WEBrick
|
61
|
+
|
62
|
+
def initialize(webrick, server)
|
63
|
+
@server = server
|
64
|
+
@server.options[:HandlerTable] = { 'xhtml' => XhtmlFileHandler }
|
65
|
+
|
66
|
+
# Handles static resources. Useful when running
|
67
|
+
# a stand-alone webrick server.
|
68
|
+
|
69
|
+
@file_handler = WEBrick::HTTPServlet::FileHandler.new(
|
70
|
+
webrick,
|
71
|
+
server.public_root,
|
72
|
+
server.options
|
73
|
+
)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Handle a static file. Also handles cached pages.
|
77
|
+
|
78
|
+
def handle_file(req, res)
|
79
|
+
begin
|
80
|
+
rewrite(req)
|
81
|
+
@file_handler.do_GET(req, res)
|
82
|
+
return true
|
83
|
+
rescue WEBrick::HTTPStatus::PartialContent, WEBrick::HTTPStatus::NotModified => err
|
84
|
+
res.set_error(err)
|
85
|
+
return true
|
86
|
+
rescue
|
87
|
+
return false
|
88
|
+
ensure
|
89
|
+
unrewrite(req)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Handle the request.
|
94
|
+
|
95
|
+
def handle(req, res)
|
96
|
+
unless handle_file(req, res)
|
97
|
+
path = req.request_uri.path
|
98
|
+
|
99
|
+
unless path =~ /\./
|
100
|
+
begin
|
101
|
+
path = req.request_uri.path
|
102
|
+
|
103
|
+
# REQUEST_MUTEX.lock
|
104
|
+
|
105
|
+
context = Context.new(@server)
|
106
|
+
|
107
|
+
context.in = StringIO.new(req.body || "")
|
108
|
+
|
109
|
+
context.headers = {}
|
110
|
+
req.header.each { |h, v| context.headers[h.upcase] = v.first }
|
111
|
+
context.headers.update(req.meta_vars)
|
112
|
+
|
113
|
+
# gmosx: make compatible with fastcgi.
|
114
|
+
context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
|
115
|
+
context.headers['REQUEST_URI'] << '/'
|
116
|
+
|
117
|
+
CgiUtils.parse_params(context)
|
118
|
+
CgiUtils.parse_cookies(context)
|
119
|
+
|
120
|
+
context.render(path)
|
121
|
+
|
122
|
+
res.status = context.status
|
123
|
+
res.instance_variable_set(:@header, context.response_headers || {})
|
124
|
+
res.instance_variable_set(:@cookies, context.response_cookies || {})
|
125
|
+
res.body = context.out
|
126
|
+
|
127
|
+
context.close
|
128
|
+
ensure
|
129
|
+
Og.manager.put_store if defined?(Og) and Og.manager
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
alias do_GET handle
|
136
|
+
alias do_POST handle
|
137
|
+
|
138
|
+
# Try to rewrite the path to a filename.
|
139
|
+
|
140
|
+
def rewrite(req)
|
141
|
+
if req.path == '/'
|
142
|
+
req.instance_variable_set(:@path_info, '/index.html')
|
143
|
+
elsif req.path =~ /^([^.]+)$/
|
144
|
+
req.instance_variable_set(:@path_info, "#{$1}/index.html")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Rewrite back to the original path.
|
149
|
+
|
150
|
+
def unrewrite(req)
|
151
|
+
if req.path == '/'
|
152
|
+
req.instance_variable_set(:@path_info, '/')
|
153
|
+
elsif req.path =~ /^([^.]+).html$/
|
154
|
+
req.instance_variable_set(:@path_info, $1)
|
155
|
+
end
|
156
|
+
end
|
166
157
|
end
|
167
158
|
|
168
159
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'nitro/controller'
|
2
|
+
|
3
|
+
require 'wee'
|
4
|
+
require 'wee/adaptors/nitro'
|
5
|
+
|
6
|
+
module Nitro
|
7
|
+
|
8
|
+
module WeeMixin
|
9
|
+
include Wee::Nitro::ControllerMixin
|
10
|
+
|
11
|
+
# Returns the output of the component.
|
12
|
+
|
13
|
+
def component(klass, options = {})
|
14
|
+
out = ''
|
15
|
+
name = options[:name] || klass.to_s
|
16
|
+
|
17
|
+
cb = Wee::CallbackRegistry.new(Wee::SequentialIdGenerator.new)
|
18
|
+
rctx = Wee::RenderingContext.new(context(), cb, Wee::HtmlWriter.new(out))
|
19
|
+
rctx.component_name = name
|
20
|
+
rctx.controller = self
|
21
|
+
rctx.redirect_action = options[:redirect_action]
|
22
|
+
|
23
|
+
unless c = components[name]
|
24
|
+
unless block = self.class.registered_components[name]
|
25
|
+
block = proc { klass.new }
|
26
|
+
self.class.register_component(name, &block)
|
27
|
+
end
|
28
|
+
make_component name, block.call
|
29
|
+
c = components[name]
|
30
|
+
end
|
31
|
+
|
32
|
+
raise "Component #{name} not found" if c.nil?
|
33
|
+
|
34
|
+
c.render(rctx)
|
35
|
+
c.callbacks = cb
|
36
|
+
|
37
|
+
return out
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add Wee-related helper methods to published objects.
|
42
|
+
|
43
|
+
class Controller
|
44
|
+
include Wee::Nitro::ControllerMixin
|
45
|
+
include WeeMixin
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# * George Moschovitis <gm@navel.gr>
|
51
|
+
# * Michael Neumann <mneumann@ntecs.de>
|
data/lib/nitro/caching.rb
CHANGED
@@ -15,26 +15,26 @@ module Nitro
|
|
15
15
|
|
16
16
|
module Caching
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
18
|
+
# Globaly enable/disable caching.
|
19
|
+
|
20
|
+
setting :caching_enabled, :default => true, :doc => 'Globaly enable/disable caching'
|
21
|
+
|
22
|
+
def self.append_features(base) #:nodoc:
|
23
|
+
super
|
24
|
+
base.send :include, Output, Actions, Fragments
|
25
|
+
base.module_eval do
|
26
|
+
# @caching_enabled = true
|
27
|
+
def self.caching_enabled?
|
28
|
+
Caching.caching_enabled # and @caching_enabled
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def caching_enabled?
|
34
|
+
Caching.caching_enabled # and self.class.get_instance_variable(:caching_enabled)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
38
|
end
|
39
39
|
|
40
40
|
end
|
@@ -6,57 +6,57 @@ module Nitro
|
|
6
6
|
|
7
7
|
module Caching
|
8
8
|
|
9
|
-
|
9
|
+
# Action caching.
|
10
10
|
|
11
|
-
|
11
|
+
module Actions
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def self.append_features(base) # :nodoc:
|
14
|
+
super
|
15
|
+
base.extend(ClassMethods)
|
16
|
+
end
|
17
17
|
|
18
|
-
|
18
|
+
module ClassMethods
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
20
|
+
def cache_action(*actions)
|
21
|
+
return unless caching_enabled?
|
22
|
+
|
23
|
+
before_filter(
|
24
|
+
%{
|
25
|
+
fragment_name = "\#\{@action_name\}\#{@request.query_string}"
|
26
|
+
if fragment = Fragment.get(fragment_name)
|
27
|
+
@out = fragment
|
28
|
+
return
|
29
|
+
end
|
30
|
+
},
|
31
|
+
:only => actions
|
32
|
+
)
|
33
|
+
|
34
|
+
after_filter(
|
35
|
+
%{
|
36
|
+
fragment_name = "\#\{@action_name\}\#{@request.query_string}"
|
37
|
+
Fragment.put(fragment_name, @out)
|
38
|
+
},
|
39
|
+
:only => actions
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
44
|
|
45
|
-
|
45
|
+
private
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
#--
|
48
|
+
# FIXME: not implemented.
|
49
|
+
#++
|
50
|
+
|
51
|
+
def expire_action(*actions)
|
52
|
+
return unless caching_enabled?
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
for action in [actions].flatten
|
55
|
+
expire_fragment(action)
|
56
|
+
end
|
57
|
+
end
|
58
58
|
|
59
|
-
|
59
|
+
end
|
60
60
|
|
61
61
|
end
|
62
62
|
|