nitro 0.23.0 → 0.24.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.
Files changed (76) hide show
  1. data/CHANGELOG +350 -0
  2. data/INSTALL +2 -2
  3. data/ProjectInfo +61 -0
  4. data/README +5 -4
  5. data/Rakefile +5 -4
  6. data/bin/nitrogen +3 -1
  7. data/doc/AUTHORS +27 -3
  8. data/doc/RELEASES +193 -0
  9. data/doc/lhttpd.txt +4 -0
  10. data/lib/nitro.rb +1 -1
  11. data/lib/nitro/adapter/cgi.rb +6 -321
  12. data/lib/nitro/adapter/fastcgi.rb +2 -14
  13. data/lib/nitro/adapter/scgi.rb +237 -71
  14. data/lib/nitro/adapter/webrick.rb +25 -7
  15. data/lib/nitro/caching.rb +1 -0
  16. data/lib/nitro/cgi.rb +296 -0
  17. data/lib/nitro/{cookie.rb → cgi/cookie.rb} +0 -0
  18. data/lib/nitro/cgi/http.rb +62 -0
  19. data/lib/nitro/{request.rb → cgi/request.rb} +4 -1
  20. data/lib/nitro/{response.rb → cgi/response.rb} +0 -0
  21. data/lib/nitro/cgi/stream.rb +43 -0
  22. data/lib/nitro/cgi/utils.rb +38 -0
  23. data/lib/nitro/compiler.rb +23 -11
  24. data/lib/nitro/compiler/css.rb +8 -0
  25. data/lib/nitro/compiler/morphing.rb +66 -0
  26. data/lib/nitro/context.rb +21 -30
  27. data/lib/nitro/controller.rb +23 -100
  28. data/lib/nitro/dispatcher.rb +18 -8
  29. data/lib/nitro/element.rb +6 -2
  30. data/lib/nitro/flash.rb +2 -2
  31. data/lib/nitro/mixin/buffer.rb +2 -2
  32. data/lib/nitro/mixin/form.rb +204 -93
  33. data/lib/nitro/mixin/javascript.rb +170 -11
  34. data/lib/nitro/mixin/markup.rb +1 -0
  35. data/lib/nitro/mixin/pager.rb +7 -4
  36. data/lib/nitro/mixin/rss.rb +2 -0
  37. data/lib/nitro/mixin/table.rb +23 -6
  38. data/lib/nitro/mixin/xhtml.rb +2 -2
  39. data/lib/nitro/render.rb +19 -5
  40. data/lib/nitro/scaffold.rb +12 -6
  41. data/lib/nitro/server.rb +4 -6
  42. data/lib/nitro/server/runner.rb +2 -2
  43. data/lib/nitro/session.rb +8 -1
  44. data/lib/nitro/session/file.rb +40 -0
  45. data/lib/part/admin.rb +2 -0
  46. data/lib/part/admin/controller.rb +7 -3
  47. data/lib/part/admin/skin.rb +8 -1
  48. data/lib/part/admin/template/index.xhtml +39 -1
  49. data/proto/public/error.xhtml +5 -3
  50. data/proto/public/js/behaviour.js +254 -254
  51. data/proto/public/js/controls.js +427 -165
  52. data/proto/public/js/dragdrop.js +255 -276
  53. data/proto/public/js/effects.js +476 -277
  54. data/proto/public/js/prototype.js +561 -127
  55. data/proto/public/js/scaffold.js +74 -0
  56. data/proto/public/js/scriptaculous.js +44 -0
  57. data/proto/public/js/util.js +548 -0
  58. data/proto/public/scaffold/list.xhtml +4 -1
  59. data/proto/scgi.rb +333 -0
  60. data/script/scgi_ctl +221 -0
  61. data/script/scgi_service +120 -0
  62. data/test/nitro/adapter/raw_post1.bin +0 -0
  63. data/test/nitro/{tc_cookie.rb → cgi/tc_cookie.rb} +1 -1
  64. data/test/nitro/{tc_request.rb → cgi/tc_request.rb} +1 -1
  65. data/test/nitro/mixin/tc_xhtml.rb +1 -1
  66. data/test/nitro/{adapter/tc_cgi.rb → tc_cgi.rb} +12 -12
  67. data/test/nitro/tc_controller.rb +9 -5
  68. metadata +159 -169
  69. data/benchmark/bench.rb +0 -5
  70. data/benchmark/simple-webrick-n-200.txt +0 -44
  71. data/benchmark/static-webrick-n-200.txt +0 -43
  72. data/benchmark/tiny-lhttpd-n-200-c-5.txt +0 -43
  73. data/benchmark/tiny-webrick-n-200-c-5.txt +0 -44
  74. data/benchmark/tiny-webrick-n-200.txt +0 -44
  75. data/benchmark/tiny2-webrick-n-200.txt +0 -44
  76. data/examples/README +0 -7
File without changes
@@ -0,0 +1,62 @@
1
+ module Nitro
2
+
3
+ # Various HTTP related constants and utilities.
4
+
5
+ module Http
6
+
7
+ # HTTP protocol EOL constants.
8
+
9
+ CR = "\x0d"
10
+ LF = "\x0a"
11
+ CRLF = "\x0d\x0a"
12
+ EOL = CRLF
13
+
14
+ # Constants for readable code.
15
+
16
+ STATUS_OK = 200
17
+ STATUS_PARTIAL_CONTENT = 206
18
+ STATUS_MOVED = 301
19
+ STATUS_REDIRECT = 302
20
+ STATUS_SEE_OTHER = 303
21
+ STATUS_SEE_OTHER_307 = 307
22
+ STATUS_NOT_MODIFIED = 304
23
+ STATUS_BAD_REQUEST = 400
24
+ STATUS_AUTH_REQUIRED = 401
25
+ STATUS_FORBIDDEN = 403
26
+ STATUS_NOT_FOUND = 404
27
+ STATUS_METHOD_NOT_ALLOWED = 405
28
+ STATUS_NOT_ACCEPTABLE = 406
29
+ STATUS_LENGTH_REQUIRED = 411
30
+ STATUS_PRECONDITION_FAILED = 412
31
+ STATUS_SERVER_ERROR = 500
32
+ STATUS_NOT_IMPLEMENTED = 501
33
+ STATUS_BAD_GATEWAY = 502
34
+ STATUS_VARIANT_ALSO_VARIES = 506
35
+
36
+ # Hash to allow id to description maping.
37
+
38
+ STATUS_STRINGS = {
39
+ 200 => "OK",
40
+ 206 => "Partial Content",
41
+ 300 => "Multiple Choices",
42
+ 301 => "Moved Permanently",
43
+ 302 => "Found",
44
+ 303 => "See other", # gmosx: VERIFY THIS
45
+ 304 => "Not Modified",
46
+ 307 => "See other 07", # gmosx: VERIFY THIS
47
+ 400 => "Bad Request",
48
+ 401 => "Authorization Required",
49
+ 403 => "Forbidden",
50
+ 404 => "Not Found",
51
+ 405 => "Method Not Allowed",
52
+ 406 => "Not Acceptable",
53
+ 411 => "Length Required",
54
+ 412 => "Precondition Failed",
55
+ 500 => "Internal Server Error",
56
+ 501 => "Method Not Implemented",
57
+ 502 => "Bad Gateway",
58
+ 506 => "Variant Also Negotiates"
59
+ }
60
+ end
61
+
62
+ end
@@ -49,7 +49,7 @@ module Request
49
49
  # The path is the uri without the query string.
50
50
 
51
51
  def path
52
- path = uri ? uri.split('?').first : ''
52
+ uri ? uri.split('?').first : ''
53
53
  end
54
54
 
55
55
  def path_info
@@ -79,6 +79,9 @@ module Request
79
79
  end
80
80
 
81
81
  # The request query string.
82
+ #--
83
+ # gmosxi, FIXME: handles some fcgi problems.
84
+ #++
82
85
 
83
86
  def query_string
84
87
  @headers['QUERY_STRING']
File without changes
@@ -0,0 +1,43 @@
1
+ require 'nitro/render'
2
+
3
+ module Nitro
4
+
5
+ module Render
6
+
7
+ # Enable streaming mode for the current
8
+ # HTTP Response.
9
+ # You can optionally provide an existing IO
10
+ # object for streaming.
11
+ #--
12
+ # This code is considered a hack fix.
13
+ # But it still is useful so for the moment
14
+ # it stays in the distribution.
15
+ #++
16
+
17
+ def stream(io = nil)
18
+ if io
19
+ # Reuse an existing IO if it exists.
20
+ @context.out = io
21
+ else
22
+ r, w = IO.pipe
23
+
24
+ @context.out = r
25
+ @out = w
26
+ r.sync = true
27
+ w.class.send(:define_method, :empty?) { false }
28
+
29
+ Thread.new do
30
+ begin
31
+ yield
32
+ rescue Object => ex
33
+ p ex
34
+ ensure
35
+ w.close
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,38 @@
1
+ require 'nitro/context'
2
+
3
+ module Nitro
4
+
5
+ module Request
6
+
7
+ # Some useful mini methods for browser testing.
8
+
9
+ def user_agent
10
  headers['HTTP_USER_AGENT'] || headers['USER-AGENT']
1
11
  end
12
+
13
+ def from_gecko?
14
+ headers['USER-AGENT'] =~ /Gecko/
15
+ end
16
+ alias_method :from_mozilla?, :from_gecko?
17
+
18
+ def from_ie?
19
+ headers['USER-AGENT'] =~ /MSIE/
20
+ end
21
+ alias_method :from_msie?, :from_ie?
22
+
23
+ def from_opera?
24
+ headers['USER-AGENT'] =~ /Opera/
25
+ end
26
+
27
+ def from_khtml?
28
+ headers['USER-AGENT'] =~ /KTHML/
29
+ end
30
+ alias_method :from_safari?, :from_khtml?
31
+
32
+ def from_w3c?
33
+ from_gecko? or from_khtml? or from_opera?
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ # * Chris Farmiloe <chris.farmiloe@farmiloe.com>
@@ -1,4 +1,4 @@
1
- require 'nano/object/singleton_class'
1
+ require 'nano/kernel/singleton'
2
2
 
3
3
  require 'glue/template'
4
4
  require 'nitro/compiler/errors'
@@ -120,8 +120,7 @@ class Compiler
120
120
 
121
121
  # Annotated parameters.
122
122
 
123
- if meta = klass.action_metadata[action.intern]
124
- params = meta.params.keys
123
+ if params = klass.ann(action.to_sym).params and (!params.nil?)
125
124
  params = params.collect { |p| "@#{p} = @context['#{p}']" }
126
125
  code << "#{params.join(';')}"
127
126
  end
@@ -142,7 +141,7 @@ class Compiler
142
141
  code << "break if i >= #{param_count};"
143
142
  end
144
143
  code << %{
145
- params << qs.split(/=/).last
144
+ params << CGI.unescape(qs.split(/=/).last)
146
145
  end
147
146
  end
148
147
  action_return_value = #{action}(*params)
@@ -167,13 +166,10 @@ class Compiler
167
166
  # better practice to place the output related code in an
168
167
  # external template file.
169
168
 
170
- # Take :view metadata into account.
171
-
172
- view = nil
173
- if md = klass.action_metadata[action.intern]
174
- view = md[:view]
175
- end
176
- view ||= action
169
+ # Take :view annotation into account.
170
+
171
+ view = klass.ann(action.to_sym).view # FIXME
172
+ view = action if view.nil?
177
173
 
178
174
  cklass = klass
179
175
  template_path = nil
@@ -258,6 +254,22 @@ class Compiler
258
254
  end
259
255
  alias_method :setup_template_transform, :setup_transform_template
260
256
  alias_method :setup_template_transformation, :setup_transform_template
257
+
258
+ # Typically used to precompile css templates.
259
+
260
+ def precompile(filename)
261
+ src = File.join(Template.root, "#{filename}t")
262
+ dst = File.join(Server.public_root, filename)
263
+
264
+ if (!File.exist?(dst)) or (File.mtime(src) > File.mtime(dst))
265
+ Logger.info "Compiling template '#{src}' to '#{dst}'."
266
+ template = FileTemplate.new(src)
267
+ File.open(dst, 'w') do |f|
268
+ f << template.process
269
+ end
270
+ end
271
+ end
272
+
261
273
  end
262
274
 
263
275
  end
@@ -0,0 +1,8 @@
1
+ #
2
+
3
+
4
+
5
+ __END__
6
+
7
+ Compiler.precompile('style.xcss')
8
+
@@ -0,0 +1,66 @@
1
+ module Nitro::Compiler
2
+
3
+ # A module that expand xhtml tags to ruby code
4
+ # according to some tag attributes. (if, unless, each)
5
+ #--
6
+ # FIXME: nested tags are not handled correctly. We should
7
+ # reimplement this using REXML or something.
8
+ #++
9
+
10
+ module Morphing
11
+
12
+ def self.transform(input_text)
13
+ text = input_text.dup
14
+ # <tag if="x">..</tag>
15
+ # <tag unless="x">..</tag>
16
+ #
17
+ # example:
18
+ #
19
+ # <div prop1="one" if="@mycond" prop2="two">@mycond is true</div>
20
+ #
21
+ # becomes
22
+ #
23
+ # <?r if @mycond ?>
24
+ # <div prop1="one" prop2="two">@mycond is true</div>
25
+ # <?r end ?>
26
+
27
+ text.gsub!(/<(\w*?)([^>]*?)(if|unless)=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
28
+ %{<?r #$3 #$4 ?>
29
+ <#$1#$2#$5>#$6</#$1>
30
+ <?r end ?>}
31
+ end
32
+
33
+ # <tag times="x">..</tag>
34
+
35
+ text.gsub!(/<(\w*?)([^>]*?)times=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
36
+ %{<?r #$3.times do ?>
37
+ <#$1#$2#$4>#$5</#$1>
38
+ <?r end ?>}
39
+ end
40
+
41
+ # <tag each="x">..</tag>
42
+ #
43
+ # example:
44
+ #
45
+ # <li each="item in array">my item is #{item}</li>
46
+ #
47
+ # becomes
48
+ #
49
+ # <?r for item in array ?>
50
+ # <li>my item is #{item}</li>
51
+ # <?r end ?>
52
+
53
+ text.gsub!(/<(\w*?)([^>]*?)each=["|'](.*?)["|'](.*?)>(.*?)<\/\1>/m) do |match|
54
+ %{<?r for #$3 ?>
55
+ <#$1#$2#$4>#$5</#$1>
56
+ <?r end ?>}
57
+ end
58
+
59
+ text
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ # * George Moschovitis <gm@navel.gr>
data/lib/nitro/context.rb CHANGED
@@ -1,15 +1,20 @@
1
- require 'nano/object/assign_with'
1
+ require 'nano/kernel/assign_with'
2
2
 
3
- require 'nitro/request'
4
- require 'nitro/response'
3
+ require 'nitro/cgi'
4
+ require 'nitro/cgi/request'
5
+ require 'nitro/cgi/response'
5
6
  require 'nitro/render'
6
7
  require 'nitro/session'
7
- require 'nitro/adapter/cgi.rb'
8
8
 
9
9
  module Nitro
10
10
 
11
11
  # Encapsulates an HTTP processing cycle context.
12
- # Integrates the Request and the Response.
12
+ # Integrates the HTTP Request, the HTTP Response
13
+ # and the Render used to generate the response
14
+ # body.
15
+ # The Context object can be accessed by the
16
+ # context, request or response aliases. You can
17
+ # use the alias that makes sense every time.
13
18
 
14
19
  class Context
15
20
  include Request
@@ -38,12 +43,12 @@ class Context
38
43
 
39
44
  # initialize response.
40
45
 
41
- @status = CgiUtils::STATUS_OK
46
+ @status = Http::STATUS_OK
42
47
  @response_headers = { 'Content-Type' => 'text/html' }
43
48
 
44
49
  # initialize the output buffer.
45
50
 
46
- @out = OutputBuffer.new
51
+ @out ||= OutputBuffer.new
47
52
  end
48
53
 
49
54
  # Close the context, should be called at the
@@ -77,32 +82,18 @@ class Context
77
82
 
78
83
  # Populate an object from request parameters.
79
84
  # This is a truly dangerous method.
85
+ #
86
+ # === Options
87
+ #
88
+ # * name
89
+ # * force_boolean
80
90
 
81
- EXCLUDED_PARAMETERS = %w{ oid name }
82
-
83
- def fill(obj, name = nil)
84
- # If an class is passed create an instance.
85
- obj = obj.new if obj.is_a?(Class)
86
-
87
- @params.each do |param, val|
88
- begin
89
- # gmosx: DO NOT escape by default !!!
90
- if not EXCLUDED_PARAMETERS.include?(param)
91
- if val.is_a? Hash
92
- obj.send("__force_hash_#{param}", val)
93
- else
94
- obj.send("__force_#{param}", val)
95
- end
96
- end
97
- rescue NameError => ex
98
- next
99
- end
100
- end
101
-
102
- return obj
103
- end
91
+ def fill(obj, options = {})
92
+ Property.populate_object(obj, @params, options)
93
+ end
104
94
  alias_method :populate, :fill
105
95
  alias_method :assign, :fill
96
+
106
97
  end
107
98
 
108
99
  end
@@ -1,3 +1,5 @@
1
+ require 'mega/annotation'
2
+
1
3
  require 'glue/aspects'
2
4
  require 'glue/helper'
3
5
 
@@ -26,61 +28,13 @@ unless const_defined? :ActionParam
26
28
  ActionParam = Struct.new(:default, :format, :required)
27
29
  end
28
30
 
29
- # Encapsulates metadata that describe an action.
30
-
31
- class ActionMeta < Hash
32
-
33
- # The arguments of the given method.
34
-
35
- attr_accessor :params
36
-
37
- # Initialize the metadata.
38
-
39
- def initialize(options = {})
40
- @params = {}
41
- update(options)
42
- end
43
-
44
- # Update the metadata.
45
- #
46
- # [+options+]
47
- # A hash containing the metadata. Options with Symbol
48
- # keys are considered metadata, options with
49
- # String keys are the named parameters for the action.
50
-
51
- def update(options)
52
- options.each do |k, v|
53
- case k
54
- when String
55
- # A key of type String denotes a parameter.
56
- case v
57
- when Regexp
58
- @params[k] = ActionParam.new(nil, v, nil)
59
- when ActionParam
60
- @params[k] = v
61
- else
62
- if v == :required
63
- @params[k] = ActionParam.new(nil, nil, true)
64
- else
65
- @params[k] = ActionParam.new(v, nil, nil)
66
- end
67
- end
68
- when Symbol
69
- self[k] = v
70
- else
71
- raise TypeError.new('The keys must be either Symbols or Strings.')
72
- end
73
- end
74
- end
75
-
76
- end
77
-
78
31
  # Include this Mixin to a class to make objects of this class
79
32
  # publishable, ie accessible through a standard web (REST)
80
33
  # interface.
81
34
 
82
35
  module Publishable
83
36
  def self.append_features(base)
37
+ super
84
38
 
85
39
  base.module_eval do
86
40
  include Render
@@ -88,35 +42,33 @@ module Publishable
88
42
  include Flashing
89
43
  include Glue::Helpers
90
44
 
91
- class << self
92
- attr_accessor :template_root
93
- end
94
- end
95
-
96
- # Define metadata for an action. This is a helper
97
- # macro.
98
-
99
- base.module_eval do
100
- def self.action(name, options)
101
- if meta = action_metadata[name]
102
- meta.update(options)
103
- else
104
- action_metadata[name] = ActionMeta.new(options)
105
- end
45
+ # Override this method as needed. Unless overriden
46
+ # this method is initialized by the Dispatcher to
47
+ # point to Template.root/path for each Controller.
48
+
49
+ def self.template_root
50
+ nil
51
+ end
52
+
53
+ private
54
+
55
+ # Helper method.
56
+
57
+ def template_root
58
+ self.class.template_root || Template.root
106
59
  end
107
60
  end
108
61
 
109
62
  # Aliases an action
110
63
  #--
111
64
  # gmosx, FIXME: better implementation needed.
65
+ # gmosx, FIXME: copy all annotations.
112
66
  #++
113
67
 
114
68
  base.module_eval do
115
69
  def self.alias_action(new, old)
116
70
  alias_method new, old
117
- md = action_metadata[old] || ActionMeta.new
118
- md[:view] = old
119
- action_metadata[new] = md
71
+ ann new, :view => old
120
72
  end
121
73
  end
122
74
 
@@ -142,17 +94,6 @@ module Publishable
142
94
  return methods
143
95
  end
144
96
  end
145
-
146
- # A hash containing metadata for the action
147
- # methods.
148
-
149
- base.module_eval do
150
- def self.action_metadata
151
- # FIXME: improve this.
152
- @action_metadata ||= {}
153
- @action_metadata
154
- end
155
- end
156
97
 
157
98
  # Use the method_missing hook to compile the actions
158
99
  # for this controller.
@@ -168,6 +109,9 @@ module Publishable
168
109
  end
169
110
 
170
111
  # Cookie helpers.
112
+ #--
113
+ # TODO: move elsewhere.
114
+ #++
171
115
 
172
116
  base.module_eval do
173
117
  private
@@ -192,28 +136,7 @@ class Controller
192
136
  include Publishable
193
137
  include Scaffolding
194
138
  include Caching
195
- include Markup
196
-
197
- # The default action.
198
- =begin
199
- def index
200
- print %{
201
- This is the placeholder action is provided as a default for #{self.class.name}.<br />
202
- You probably want to <b>implement your custom action</b> here.
203
- }
204
- end
205
- =end
206
- end
207
-
208
- # A simple controller, only handles templates.
209
- # Useful to implement php/asp/jsp style applications.
210
- # The Dispatcher uses this as the default Controller.
211
- #--
212
- # gmosx: At the moment used to have a separate
213
- # template_root.
214
- #++
215
-
216
- class SimpleController < Controller
139
+ include Markup
217
140
  end
218
141
 
219
142
  end