nitro 0.29.0 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +410 -0
- data/ProjectInfo +36 -44
- data/README +5 -5
- data/doc/AUTHORS +6 -0
- data/doc/RELEASES +159 -2
- data/lib/glue/sweeper.rb +2 -2
- data/lib/glue/webfile.rb +14 -1
- data/lib/nitro.rb +6 -9
- data/lib/nitro/adapter/mongrel.rb +36 -43
- data/lib/nitro/adapter/scgi.rb +1 -1
- data/lib/nitro/adapter/webrick.rb +96 -24
- data/lib/nitro/caching/actions.rb +2 -1
- data/lib/nitro/caching/fragments.rb +1 -8
- data/lib/nitro/caching/output.rb +14 -4
- data/lib/nitro/cgi.rb +19 -21
- data/lib/nitro/cgi/cookie.rb +5 -1
- data/lib/nitro/cgi/request.rb +20 -4
- data/lib/nitro/compiler.rb +74 -28
- data/lib/nitro/compiler/cleanup.rb +1 -1
- data/lib/nitro/compiler/elements.rb +1 -2
- data/lib/nitro/compiler/localization.rb +1 -1
- data/lib/nitro/compiler/markup.rb +1 -1
- data/lib/nitro/compiler/script.rb +52 -44
- data/lib/nitro/compiler/squeeze.rb +4 -3
- data/lib/nitro/compiler/xslt.rb +7 -6
- data/lib/nitro/context.rb +39 -20
- data/lib/nitro/controller.rb +24 -5
- data/lib/nitro/dispatcher.rb +13 -5
- data/lib/nitro/global.rb +63 -0
- data/lib/nitro/helper/feed.rb +432 -0
- data/lib/nitro/helper/form.rb +11 -3
- data/lib/nitro/helper/form/builder.rb +140 -0
- data/lib/nitro/helper/form/controls.rb +2 -1
- data/lib/nitro/helper/javascript.rb +6 -0
- data/lib/nitro/helper/javascript/morphing.rb +13 -6
- data/lib/nitro/helper/xhtml.rb +42 -6
- data/lib/nitro/helper/xml.rb +3 -0
- data/lib/nitro/part.rb +2 -2
- data/lib/nitro/render.rb +7 -2
- data/lib/nitro/router.rb +57 -16
- data/lib/nitro/scaffolding.rb +29 -20
- data/lib/nitro/server.rb +4 -10
- data/lib/nitro/server/drb.rb +1 -1
- data/lib/nitro/server/runner.rb +10 -0
- data/lib/nitro/session.rb +31 -12
- data/lib/nitro/session/drb.rb +13 -1
- data/lib/nitro/session/file.rb +1 -1
- data/lib/nitro/session/memcached.rb +1 -1
- data/lib/nitro/session/memory.rb +1 -1
- data/lib/nitro/session/og.rb +1 -1
- data/lib/nitro/test/testcase.rb +3 -0
- data/proto/public/error.xhtml +5 -5
- data/proto/public/js/controls.js +2 -2
- data/proto/public/js/dragdrop.js +320 -79
- data/proto/public/js/effects.js +200 -152
- data/proto/public/js/prototype.js +284 -63
- data/proto/public/js/scriptaculous.js +7 -5
- data/proto/public/js/unittest.js +11 -0
- data/proto/public/scaffold/advanced_search.xhtml +30 -0
- data/proto/public/scaffold/list.xhtml +8 -1
- data/proto/public/scaffold/search.xhtml +2 -1
- data/proto/script/scgi_service +1 -1
- data/src/part/admin/controller.rb +1 -1
- data/src/part/admin/skin.rb +1 -1
- data/test/nitro/CONFIG.rb +3 -0
- data/test/nitro/adapter/tc_webrick.rb +1 -1
- data/test/nitro/cgi/tc_cookie.rb +1 -1
- data/test/nitro/cgi/tc_request.rb +5 -5
- data/test/nitro/compiler/tc_client_morpher.rb +47 -0
- data/test/nitro/compiler/tc_compiler.rb +2 -0
- data/test/nitro/helper/tc_feed.rb +138 -0
- data/test/nitro/helper/tc_pager.rb +1 -1
- data/test/nitro/helper/tc_rss.rb +1 -1
- data/test/nitro/helper/tc_table.rb +1 -1
- data/test/nitro/helper/tc_xhtml.rb +1 -1
- data/test/nitro/tc_caching.rb +1 -1
- data/test/nitro/tc_cgi.rb +1 -1
- data/test/nitro/tc_context.rb +1 -1
- data/test/nitro/tc_controller.rb +31 -3
- data/test/nitro/tc_controller_aspect.rb +1 -1
- data/test/nitro/tc_dispatcher.rb +1 -1
- data/test/nitro/tc_element.rb +1 -1
- data/test/nitro/tc_flash.rb +1 -1
- data/test/nitro/tc_helper.rb +1 -1
- data/test/nitro/tc_render.rb +6 -6
- data/test/nitro/tc_router.rb +8 -4
- data/test/nitro/tc_server.rb +1 -3
- data/test/nitro/tc_session.rb +1 -3
- metadata +107 -104
- data/Rakefile +0 -232
- data/lib/nitro/adapter/acgi.rb +0 -237
- data/proto/public/Makefile.acgi +0 -40
- data/proto/public/acgi.c +0 -138
data/README
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Nitro 0.
|
1
|
+
= Nitro 0.30.0 README
|
2
2
|
|
3
3
|
Nitro provides everything you need to develop professional Web
|
4
4
|
applications using Ruby and Javascript.
|
@@ -325,14 +325,14 @@ doc/RELEASES
|
|
325
325
|
|
326
326
|
The latest version of Nitro can be found at
|
327
327
|
|
328
|
-
* http://www.
|
328
|
+
* http://www.nitroproject.org
|
329
329
|
|
330
330
|
|
331
331
|
== Documentation
|
332
332
|
|
333
333
|
Documentation for Nitro can be found at
|
334
334
|
|
335
|
-
* http://www.
|
335
|
+
* http://www.nitroproject.org
|
336
336
|
|
337
337
|
Don't forget to read the file doc/RELEASES for usefull
|
338
338
|
documentation bits. Also, have a look at the test cases in
|
@@ -344,7 +344,7 @@ the test directory for examples of usage.
|
|
344
344
|
A number of videos that demonstrate Nitro in practical usage
|
345
345
|
are available here:
|
346
346
|
|
347
|
-
http://www.
|
347
|
+
http://www.nitroproject.org/view/Videos
|
348
348
|
|
349
349
|
|
350
350
|
== Requirements
|
@@ -549,7 +549,7 @@ http://rubyforge.org/mailman/listinfo/nitro-general
|
|
549
549
|
Copyright (c) 2004-2006, George 'gmosx' Moschovitis (http://www.gmosx.com)
|
550
550
|
Copyright (c) 2004-2006, Navel Ltd (http://www.navel.gr)
|
551
551
|
|
552
|
-
Nitro (http://www.
|
552
|
+
Nitro (http://www.nitroproject.org) is copyrighted free software
|
553
553
|
created and maintained by George Moschovitis (mailto:gm@navel.gr)
|
554
554
|
and released under the standard BSD Licence. For details consult
|
555
555
|
the file LICENCE.
|
data/doc/AUTHORS
CHANGED
@@ -50,6 +50,12 @@ IDEAS, ADDITIONAL CODING, SUPPORT:
|
|
50
50
|
* TRANS <transfire@gmail.com>
|
51
51
|
Small bug fixes, patches.
|
52
52
|
|
53
|
+
* Kashia Buch <kashia@vfemail.net>
|
54
|
+
Patches, documentation.
|
55
|
+
|
56
|
+
* Massimo Maria Ghisalberti
|
57
|
+
Patches.
|
58
|
+
|
53
59
|
* Dan Yoder <dan@zeraweb.com>
|
54
60
|
Original 'Elements' implementation, bug reports.
|
55
61
|
|
data/doc/RELEASES
CHANGED
@@ -1,3 +1,160 @@
|
|
1
|
+
== Version 0.30.0
|
2
|
+
|
3
|
+
Another pragmatic release. The Nitro development team worked over
|
4
|
+
the submitted tickets and provided many bug fixes. More over, there
|
5
|
+
are many small improvements along the codebase and as always
|
6
|
+
we could not resist adding some cool new features.
|
7
|
+
|
8
|
+
Special thanks fly to Bryan Sotto for making this release
|
9
|
+
possible!
|
10
|
+
|
11
|
+
Most notable chages:
|
12
|
+
|
13
|
+
* Nitro allows fine grained customization of the compiler
|
14
|
+
tranformation pipeline per controller or even per action.
|
15
|
+
Here come some examples:
|
16
|
+
|
17
|
+
class MyController
|
18
|
+
ann :self, :transformation_pipeline => [MyTransformer, AnotherXForm]
|
19
|
+
|
20
|
+
...
|
21
|
+
|
22
|
+
def my_action
|
23
|
+
...
|
24
|
+
end
|
25
|
+
ann :my_action, :transformation_pipeline => Compiler.transformation_pipeline.dup.shift(CustomXForm)
|
26
|
+
|
27
|
+
...
|
28
|
+
end
|
29
|
+
|
30
|
+
* Nitro automates integration testing by means of the new
|
31
|
+
session VCR feature that allows for easy proxy based
|
32
|
+
functional testing. A typicall session goes like this:
|
33
|
+
|
34
|
+
Start your app with:
|
35
|
+
|
36
|
+
ruby run.rb --record myfile
|
37
|
+
|
38
|
+
Then use your web browser to 'perform' your testing session.
|
39
|
+
You can used multiple browsers, concurrent users and hit all
|
40
|
+
the pages in your app. At the end, just stop the server.
|
41
|
+
|
42
|
+
In order to perform regression testing against this recorded
|
43
|
+
session just restart the server in playback mode:
|
44
|
+
|
45
|
+
ruby run.rb --playback myfile
|
46
|
+
|
47
|
+
Nitro automatically plays back the recorded session and logs
|
48
|
+
any errors or Exceptions.
|
49
|
+
|
50
|
+
* Better Global variable implementation works better with
|
51
|
+
distributed stores (Drb, Memcached). Notice the new
|
52
|
+
Global.init and Global[:key].update { |v| } methods.
|
53
|
+
|
54
|
+
* Improved the Router implementation. One notable addition
|
55
|
+
is support for global router initialization:
|
56
|
+
|
57
|
+
Router.rules = [
|
58
|
+
{ :match => /~(.*)/, :controller => IdController, :action => :view, :params => [:name] }
|
59
|
+
]
|
60
|
+
|
61
|
+
* Cleaned up glue by removing files duplicating functionality
|
62
|
+
allready available in Facets. Moreover, we moved several
|
63
|
+
generally useful files and methods from Glue to Facets.
|
64
|
+
|
65
|
+
* Replaced the old RSSHelper with the new FeedHelper. The new
|
66
|
+
implementation provides support for RSS, Atom, OPML. The
|
67
|
+
FeedHelper is backwards compatible with the old helper but
|
68
|
+
provides even more features.
|
69
|
+
|
70
|
+
class MyController
|
71
|
+
helper :feed
|
72
|
+
end
|
73
|
+
|
74
|
+
* Added Og query by example support. Query the database for an
|
75
|
+
entity that matches the example. The example is a hash
|
76
|
+
populated with the property values to search for.
|
77
|
+
|
78
|
+
The provided property values are joined with AND to build
|
79
|
+
the actual query.
|
80
|
+
|
81
|
+
Article.query_by_example :title => 'IBM%', :hits => 2
|
82
|
+
Article.find_with_properties :title => 'IBM%', :hits => 2
|
83
|
+
|
84
|
+
* Added type casting support for Og aggregations and
|
85
|
+
calculations.
|
86
|
+
|
87
|
+
* Greatly improved the configuration system. One noteable
|
88
|
+
(and extremely useful) new feature is that you can now
|
89
|
+
customize classes before they are even defined:
|
90
|
+
|
91
|
+
|
92
|
+
Configuration.User.crypt_salt = 'HELLO'
|
93
|
+
require 'users'
|
94
|
+
|
95
|
+
in users.rb:
|
96
|
+
|
97
|
+
class User
|
98
|
+
setting :crypt_salt, :default => 'DF', :doc => 'The crypt salt'
|
99
|
+
end
|
100
|
+
|
101
|
+
* Calculate rendering level in actions to allow for conditional
|
102
|
+
rendering in top level actions or sub-actions. Some helpers
|
103
|
+
are also provided:
|
104
|
+
|
105
|
+
def myaction
|
106
|
+
if request.is_top_level?
|
107
|
+
...
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
* Introduced an alternative more sophisticated (yet intuitive)
|
112
|
+
form builder. While this new helper is still under construction,
|
113
|
+
it is already very useful. Here come some examples:
|
114
|
+
|
115
|
+
<!-- entity backed form -->
|
116
|
+
|
117
|
+
<div id="myform">
|
118
|
+
#{form :object => @owner, :action => :save_profile do |f|
|
119
|
+
f.property :name, :editable => false
|
120
|
+
f.property :password
|
121
|
+
f.br
|
122
|
+
f.submit 'Update'
|
123
|
+
end}
|
124
|
+
</div>
|
125
|
+
|
126
|
+
<!-- form with virtual method (:multipart),
|
127
|
+
special controls (:select_file) -->
|
128
|
+
|
129
|
+
<div id="myform">
|
130
|
+
#{form :method => :multipart do |f|
|
131
|
+
f.p {
|
132
|
+
f.label 'Select the new icon filename'
|
133
|
+
f.select_file :file, :label => 'Select icon'
|
134
|
+
}
|
135
|
+
f.p {
|
136
|
+
f.submit 'Change'
|
137
|
+
}
|
138
|
+
end}
|
139
|
+
</div>
|
140
|
+
|
141
|
+
* More flexible Script generator, the developer can use most of
|
142
|
+
its features without a Client subclass.
|
143
|
+
|
144
|
+
* Reimplemented session garbage collection.
|
145
|
+
|
146
|
+
* Added many more RDoc comments to the source code.
|
147
|
+
|
148
|
+
* Many, many bug fixes.
|
149
|
+
|
150
|
+
* Updated to latest Facets, Scriptaculous, Prototype.
|
151
|
+
|
152
|
+
|
153
|
+
Please note that the project home page has been moved to:
|
154
|
+
|
155
|
+
http://www.nitroproject.org
|
156
|
+
|
157
|
+
|
1
158
|
== Version 0.29.0
|
2
159
|
|
3
160
|
A bold step towards maturity. Great care was taken to
|
@@ -1098,7 +1255,7 @@ Another superb release! State of the art AJAX/Javascript support,
|
|
1098
1255
|
Wee components / programmatic renderer integration, a beginners
|
1099
1256
|
tutorial, self documenting configuration and many important bug
|
1100
1257
|
fixes. Don't forget to check out our new community site at
|
1101
|
-
http://www.
|
1258
|
+
http://www.nitroproject.org
|
1102
1259
|
|
1103
1260
|
Some notable changes:
|
1104
1261
|
|
@@ -1297,7 +1454,7 @@ Some notable changes:
|
|
1297
1454
|
|
1298
1455
|
* This is surely the most request feature: Nitro Step by Step
|
1299
1456
|
by James Britt, a beginers guide to Nitro. Available in the
|
1300
|
-
brand-new, Nitro-powered, www.
|
1457
|
+
brand-new, Nitro-powered, www.nitroproject.org Community wiki.
|
1301
1458
|
|
1302
1459
|
* New examples: The totaly recoded and ultra cool ajax example,
|
1303
1460
|
a Wee/Nitro example and the new Hello world example.
|
data/lib/glue/sweeper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'facets/more/aspects'
|
2
2
|
|
3
3
|
module Glue
|
4
4
|
|
@@ -12,7 +12,7 @@ module Glue
|
|
12
12
|
#++
|
13
13
|
|
14
14
|
module Sweeper
|
15
|
-
include
|
15
|
+
include ::Aspects
|
16
16
|
|
17
17
|
before "sweep_affected(:insert)", :on => :og_insert
|
18
18
|
before "sweep_affected(:update)", :on => :og_update
|
data/lib/glue/webfile.rb
CHANGED
@@ -5,6 +5,20 @@ require 'facet/inheritor'
|
|
5
5
|
module Glue
|
6
6
|
|
7
7
|
# A Web File.
|
8
|
+
#
|
9
|
+
# You can customize the path where the uploaded file will be
|
10
|
+
# by defining a webfile_path class method *before* the property:
|
11
|
+
#
|
12
|
+
# class Icon
|
13
|
+
# def self.webfile_path request, name
|
14
|
+
# File.join(Uploads.public_root, request.user.name, 'icon.png')
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# property :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' }
|
18
|
+
# end
|
19
|
+
#--
|
20
|
+
# TODO: webfile_path customization sucks, should be improved!
|
21
|
+
#++
|
8
22
|
|
9
23
|
class WebFile
|
10
24
|
|
@@ -65,7 +79,6 @@ class WebFile
|
|
65
79
|
def #{name}_from_request(request)
|
66
80
|
param = request['#{name}']
|
67
81
|
}
|
68
|
-
|
69
82
|
if base.respond_to? :webfile_path
|
70
83
|
code << %{
|
71
84
|
path = #{base}.webfile_path(request, '#{name}')
|
data/lib/nitro.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# = Nitro
|
2
2
|
#
|
3
|
-
# Copyright (c) 2004-
|
4
|
-
# Copyright (c) 2004-
|
3
|
+
# Copyright (c) 2004-2006, George Moschovitis (http://www.gmosx.com)
|
4
|
+
# Copyright (c) 2004-2006, Navel Ltd (http://www.navel.gr)
|
5
5
|
#
|
6
|
-
# Nitro (http://www.
|
6
|
+
# Nitro (http://www.nitroproject.org) is copyrighted free software
|
7
7
|
# created and maintained by George Moschovitis (mailto:gm@navel.gr)
|
8
8
|
# and released under the standard BSD Licence. For details
|
9
9
|
# consult the file doc/LICENCE.
|
@@ -16,7 +16,7 @@ module Nitro
|
|
16
16
|
|
17
17
|
# The version.
|
18
18
|
|
19
|
-
Version = '0.
|
19
|
+
Version = '0.30.0'
|
20
20
|
|
21
21
|
# Library path.
|
22
22
|
|
@@ -39,6 +39,7 @@ end
|
|
39
39
|
# gmosx: leave them here.
|
40
40
|
#++
|
41
41
|
|
42
|
+
require 'nitro/global'
|
42
43
|
require 'nitro/context'
|
43
44
|
require 'nitro/controller'
|
44
45
|
require 'nitro/dispatcher'
|
@@ -95,11 +96,7 @@ module Nitro
|
|
95
96
|
|
96
97
|
end
|
97
98
|
|
98
|
-
|
99
|
-
# temporal store, will be moved to the actuall cache in
|
100
|
-
# Server.start
|
101
|
-
|
102
|
-
$global = $application = {}
|
99
|
+
$global = $application = Global
|
103
100
|
|
104
101
|
end
|
105
102
|
|
@@ -138,59 +138,53 @@ class MongrelAdapter < ::Mongrel::HttpHandler
|
|
138
138
|
unless handle_file(req, res)
|
139
139
|
path = req.path_info
|
140
140
|
|
141
|
-
|
142
|
-
|
143
|
-
context = Context.new(@server)
|
141
|
+
begin
|
142
|
+
context = Context.new(@server)
|
144
143
|
|
145
|
-
|
144
|
+
context.in = StringIO.new(req.body || "")
|
146
145
|
|
147
|
-
|
148
|
-
|
149
|
-
|
146
|
+
context.headers = {}
|
147
|
+
req.params.each { |h, v|
|
148
|
+
if h =~ /\AHTTP_(.*)\Z/
|
150
149
|
context.headers[$1.gsub("_", "-")] = v
|
151
150
|
end
|
152
151
|
context.headers[h] = v
|
153
|
-
|
154
|
-
|
152
|
+
}
|
153
|
+
# context.headers.update(req.meta_vars)
|
155
154
|
|
156
|
-
|
155
|
+
context.headers['REQUEST_URI'] = context.headers['SCRIPT_NAME']
|
157
156
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
157
|
+
if context.headers['PATH_INFO'].blank?
|
158
|
+
context.headers['REQUEST_URI'] = '/'
|
159
|
+
else
|
160
|
+
context.headers['REQUEST_URI'] = '/' + context.headers['PATH_INFO']
|
161
|
+
end
|
163
162
|
|
164
|
-
|
165
|
-
#context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
|
166
|
-
# context.headers['REQUEST_URI'] << '/'
|
163
|
+
# gmosx: make compatible with fastcgi.
|
167
164
|
|
168
|
-
|
169
|
-
|
165
|
+
context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
|
166
|
+
context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI']
|
170
167
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
headers = context.response_headers
|
183
|
-
headers["Content-length"] = context.out.size
|
184
|
-
headers.each { |h,v| res.socket << "#{h}: #{v}\r\n" }
|
185
|
-
res.socket << "\r\n"
|
186
|
-
|
187
|
-
# TODO handle setting cookies
|
188
|
-
res.socket << context.out
|
189
|
-
|
190
|
-
context.close
|
191
|
-
ensure
|
192
|
-
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager)
|
168
|
+
Cgi.parse_params(context)
|
169
|
+
Cgi.parse_cookies(context)
|
170
|
+
|
171
|
+
context.render(path)
|
172
|
+
|
173
|
+
res.socket << "HTTP/1.1 #{context.status.to_s} "
|
174
|
+
|
175
|
+
if STATUS_CODES.has_key? context.status
|
176
|
+
res.socket << STATUS_CODES[context.status]
|
177
|
+
else
|
178
|
+
res.socket << "Unknown Status Code"
|
193
179
|
end
|
180
|
+
res.socket << "\r\n"
|
181
|
+
|
182
|
+
res.socket << Cgi.response_headers(context)
|
183
|
+
res.socket << context.out
|
184
|
+
|
185
|
+
context.close
|
186
|
+
ensure
|
187
|
+
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager
|
194
188
|
end
|
195
189
|
end
|
196
190
|
end
|
@@ -218,4 +212,3 @@ end
|
|
218
212
|
|
219
213
|
# * Joshua Hoke
|
220
214
|
# * George Moschovitis <gm@navel.gr>
|
221
|
-
|
data/lib/nitro/adapter/scgi.rb
CHANGED
@@ -168,7 +168,7 @@ module SCGI # :nodoc: all
|
|
168
168
|
Nitro::Cgi.process(@server, cgi, cgi.stdinput, cgi.stdoutput)
|
169
169
|
#end
|
170
170
|
ensure
|
171
|
-
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager)
|
171
|
+
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
@@ -32,6 +32,7 @@ class Webrick
|
|
32
32
|
end
|
33
33
|
|
34
34
|
webrick_options = server.options.dup
|
35
|
+
|
35
36
|
require 'webrick/https' if webrick_options[:SSLEnable]
|
36
37
|
|
37
38
|
webrick_options.update(
|
@@ -43,6 +44,10 @@ class Webrick
|
|
43
44
|
[wblog, WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
44
45
|
]
|
45
46
|
)
|
47
|
+
|
48
|
+
enable_record_mode($record_session_filename) if $record_session_filename
|
49
|
+
enable_playback_mode($playback_session_filename) if $playback_session_filename
|
50
|
+
|
46
51
|
@webrick = WEBrick::HTTPServer.new(webrick_options)
|
47
52
|
|
48
53
|
trap('INT') { stop }
|
@@ -65,6 +70,75 @@ class Webrick
|
|
65
70
|
|
66
71
|
def initialize_webrick(server)
|
67
72
|
end
|
73
|
+
|
74
|
+
# Enables session recording. The recorded data can be used
|
75
|
+
# for automatic app testing by means of the playback mode.
|
76
|
+
|
77
|
+
def enable_record_mode(filename = 'session.yaml')
|
78
|
+
Logger.info "Recording application server session to '#{filename}'."
|
79
|
+
|
80
|
+
require 'facets/core/file/self/create'
|
81
|
+
|
82
|
+
$record_session = []
|
83
|
+
$last_record_time = Time.now
|
84
|
+
|
85
|
+
Nitro::WebrickAdapter.class_eval %{
|
86
|
+
def do_GET(req, res)
|
87
|
+
record_context(req, res)
|
88
|
+
handle(req, res)
|
89
|
+
end
|
90
|
+
alias_method :do_POST, :do_GET
|
91
|
+
|
92
|
+
def record_context(req, res)
|
93
|
+
delta = Time.now - $last_record_time
|
94
|
+
$last_record_time = Time.now
|
95
|
+
$record_session << [delta, req, res]
|
96
|
+
end
|
97
|
+
}
|
98
|
+
|
99
|
+
at_exit do
|
100
|
+
File.create(filename, YAML.dump($record_session))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Playback a recorded session. Typically used for testing.
|
105
|
+
|
106
|
+
def enable_playback_mode(filename = 'session.yaml')
|
107
|
+
Logger.info "Playing back application server session from '#{filename}'."
|
108
|
+
|
109
|
+
$playback_session = YAML.load_file(filename)
|
110
|
+
$playback_exception_count = 0
|
111
|
+
|
112
|
+
WEBrick::HTTPServer.class_eval %{
|
113
|
+
def start(&block)
|
114
|
+
run(nil)
|
115
|
+
end
|
116
|
+
|
117
|
+
def run(sock)
|
118
|
+
while true
|
119
|
+
delta, req, res = $playback_session.shift
|
120
|
+
|
121
|
+
if delta
|
122
|
+
sleep(delta)
|
123
|
+
begin
|
124
|
+
service(req, res)
|
125
|
+
rescue Object => ex
|
126
|
+
$playback_exception_count += 1
|
127
|
+
p '---', ex
|
128
|
+
end
|
129
|
+
else
|
130
|
+
return
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
}
|
135
|
+
|
136
|
+
at_exit do
|
137
|
+
puts "\n\n"
|
138
|
+
puts "Playback raised #$playback_exception_count exceptions.\n"
|
139
|
+
puts "\n"
|
140
|
+
end
|
141
|
+
end
|
68
142
|
|
69
143
|
end
|
70
144
|
|
@@ -127,39 +201,37 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
|
127
201
|
unless handle_file(req, res)
|
128
202
|
path = req.request_uri.path
|
129
203
|
|
130
|
-
|
131
|
-
|
132
|
-
path = req.request_uri.path
|
204
|
+
begin
|
205
|
+
path = req.request_uri.path
|
133
206
|
|
134
|
-
|
207
|
+
context = Context.new(@server)
|
135
208
|
|
136
|
-
|
209
|
+
context.in = StringIO.new(req.body || "")
|
137
210
|
|
138
|
-
|
139
|
-
|
140
|
-
|
211
|
+
context.headers = {}
|
212
|
+
req.header.each { |h, v| context.headers[h.upcase] = v.first }
|
213
|
+
context.headers.update(req.meta_vars)
|
141
214
|
|
142
|
-
|
215
|
+
# gmosx: make compatible with fastcgi.
|
143
216
|
|
144
|
-
|
145
|
-
|
217
|
+
context.headers['REQUEST_URI'].slice!(/http:\/\/(.*?)\//)
|
218
|
+
context.headers['REQUEST_URI'] = '/' + context.headers['REQUEST_URI']
|
146
219
|
|
147
|
-
|
148
|
-
|
220
|
+
Cgi.parse_params(context)
|
221
|
+
Cgi.parse_cookies(context)
|
149
222
|
|
150
|
-
|
223
|
+
context.render(path)
|
151
224
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
225
|
+
res.status = context.status
|
226
|
+
res.instance_variable_set(:@header, context.response_headers || {})
|
227
|
+
res.instance_variable_set(:@cookies, context.response_cookies || {})
|
228
|
+
res.body = context.out
|
229
|
+
res.chunked = true if context.out.is_a?(IO) and context["SERVER_PROTOCOL"] == "HTTP/1.1"
|
157
230
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
end
|
231
|
+
context.close
|
232
|
+
ensure
|
233
|
+
$autoreload_dirty = false
|
234
|
+
Og.manager.put_store if defined?(Og) and Og.respond_to?(:manager) and Og.manager
|
163
235
|
end
|
164
236
|
end
|
165
237
|
end
|