nitro 0.8.0 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. data/AUTHORS +3 -4
  2. data/ChangeLog +418 -0
  3. data/LICENSE +1 -1
  4. data/README +157 -89
  5. data/RELEASES +50 -0
  6. data/Rakefile +5 -7
  7. data/benchmark/nitro/bench.rb +5 -0
  8. data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
  9. data/benchmark/nitro/static-webrick-n-200.txt +43 -0
  10. data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
  11. data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
  12. data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
  13. data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
  14. data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
  15. data/bin/proto/README +2 -2
  16. data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
  17. data/bin/proto/conf/app.conf.rb +22 -0
  18. data/bin/proto/conf/lhttpd.conf +236 -0
  19. data/bin/proto/ctl +4 -0
  20. data/bin/proto/lib/README +5 -0
  21. data/bin/proto/log/README +3 -0
  22. data/bin/proto/root/fcgi.rb +6 -0
  23. data/bin/proto/root/index.xhtml +65 -7
  24. data/bin/proto/root/m/nitro.png +0 -0
  25. data/examples/blog/README +7 -5
  26. data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
  27. data/examples/blog/conf/app.conf.rb +56 -0
  28. data/examples/blog/conf/lhttpd.conf +236 -0
  29. data/examples/blog/ctl +4 -0
  30. data/examples/blog/lib/blog.rb +11 -136
  31. data/examples/blog/lib/blog/controller.rb +99 -0
  32. data/examples/blog/lib/blog/model.rb +39 -0
  33. data/examples/blog/log/README +3 -0
  34. data/examples/blog/root/comments.xhtml +2 -2
  35. data/examples/blog/root/fcgi.rb +6 -0
  36. data/examples/blog/root/index.xhtml +4 -5
  37. data/examples/blog/root/login.xhtml +2 -2
  38. data/examples/blog/root/style.xsl +9 -9
  39. data/examples/blog/root/view_entry.xhtml +2 -2
  40. data/examples/flash/conf/app.conf.rb +23 -0
  41. data/examples/flash/ctl +4 -0
  42. data/examples/flash/log/README +3 -0
  43. data/examples/flash/root/index.xhtml +0 -9
  44. data/examples/flash/root/show_inline_text.xhtml +10 -5
  45. data/examples/no_xsl_blog/README +12 -0
  46. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  47. data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
  48. data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
  49. data/examples/no_xsl_blog/ctl +4 -0
  50. data/examples/no_xsl_blog/lib/blog.rb +20 -0
  51. data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
  52. data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
  53. data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
  54. data/examples/no_xsl_blog/log/README +3 -0
  55. data/examples/no_xsl_blog/root/comments.xhtml +41 -0
  56. data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
  57. data/examples/no_xsl_blog/root/fcgi.rb +6 -0
  58. data/examples/no_xsl_blog/root/index.xhtml +39 -0
  59. data/examples/no_xsl_blog/root/login.xhtml +21 -0
  60. data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
  61. data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
  62. data/examples/no_xsl_blog/root/m/down.gif +0 -0
  63. data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
  64. data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
  65. data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
  66. data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
  67. data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
  68. data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
  69. data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
  70. data/examples/no_xsl_blog/root/m/obull.gif +0 -0
  71. data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
  72. data/examples/no_xsl_blog/root/m/rss.gif +0 -0
  73. data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
  74. data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
  75. data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
  76. data/examples/no_xsl_blog/root/style.css +301 -0
  77. data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
  78. data/examples/no_xsl_blog/root/view_entry.xml +12 -0
  79. data/examples/og/run.rb +2 -2
  80. data/examples/tiny/README +2 -2
  81. data/examples/tiny/conf/apache.conf +5 -0
  82. data/examples/tiny/conf/app.conf.rb +21 -0
  83. data/examples/tiny/conf/lhttpd.conf +236 -0
  84. data/examples/tiny/ctl +4 -0
  85. data/examples/tiny/log/README +3 -0
  86. data/examples/tiny/root/fcgi.rb +6 -0
  87. data/examples/tiny/root/index.xhtml +7 -4
  88. data/examples/tiny/root/nitro.png +0 -0
  89. data/lib/glue.rb +13 -9
  90. data/lib/glue/array.rb +1 -1
  91. data/lib/glue/cache.rb +1 -1
  92. data/lib/glue/flexob.rb +12 -0
  93. data/lib/glue/hash.rb +1 -1
  94. data/lib/glue/inflector.rb +2 -2
  95. data/lib/glue/logger.rb +4 -8
  96. data/lib/glue/misc.rb +14 -0
  97. data/lib/glue/number.rb +1 -1
  98. data/lib/glue/object.rb +26 -0
  99. data/lib/glue/pool.rb +1 -1
  100. data/lib/glue/property.rb +84 -91
  101. data/lib/glue/string.rb +1 -1
  102. data/lib/glue/time.rb +1 -1
  103. data/lib/glue/validation.rb +1 -1
  104. data/lib/nitro.rb +18 -6
  105. data/lib/nitro/adaptors/cgi.rb +291 -0
  106. data/lib/nitro/adaptors/fastcgi.rb +42 -0
  107. data/lib/nitro/adaptors/runner.rb +123 -0
  108. data/lib/nitro/adaptors/webrick.rb +110 -0
  109. data/lib/nitro/buffering.rb +43 -0
  110. data/lib/nitro/builders/form.rb +1 -1
  111. data/lib/nitro/builders/rss.rb +1 -1
  112. data/{bin → lib/nitro}/cluster.rb +26 -30
  113. data/lib/nitro/context.rb +82 -0
  114. data/lib/nitro/controller.rb +50 -0
  115. data/lib/nitro/cookie.rb +46 -0
  116. data/lib/nitro/dispatcher.rb +105 -0
  117. data/lib/nitro/filters.rb +9 -10
  118. data/lib/nitro/localization.rb +42 -0
  119. data/lib/nitro/mail.rb +11 -14
  120. data/lib/nitro/render.rb +275 -0
  121. data/lib/nitro/request.rb +128 -0
  122. data/lib/nitro/response.rb +38 -0
  123. data/lib/nitro/scaffold.rb +11 -11
  124. data/lib/nitro/session.rb +84 -0
  125. data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
  126. data/lib/nitro/ui/pager.rb +23 -26
  127. data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
  128. data/lib/nitro/uri.rb +1 -1
  129. data/lib/nitro/version.rb +10 -8
  130. data/lib/og.rb +66 -65
  131. data/lib/og/backend.rb +1 -1
  132. data/lib/og/backends/mysql.rb +48 -52
  133. data/lib/og/backends/psql.rb +34 -37
  134. data/lib/og/connection.rb +15 -15
  135. data/lib/og/enchant.rb +16 -9
  136. data/lib/og/meta.rb +127 -54
  137. data/lib/og/mock.rb +18 -18
  138. data/lib/og/version.rb +6 -4
  139. data/lib/parts/content.rb +4 -8
  140. data/test/glue/tc_logger.rb +3 -0
  141. data/test/glue/tc_property.rb +19 -3
  142. data/test/nitro/adaptors/tc_cgi.rb +63 -0
  143. data/test/nitro/adaptors/tc_webrick.rb +15 -0
  144. data/test/nitro/builders/tc_xml.rb +2 -2
  145. data/test/nitro/tc_context.rb +13 -0
  146. data/test/nitro/tc_controller.rb +47 -0
  147. data/test/nitro/tc_dispatcher.rb +64 -0
  148. data/test/nitro/tc_session.rb +20 -0
  149. data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
  150. data/test/root/blog/list.xhtml +6 -0
  151. data/test/tc_og.rb +41 -4
  152. metadata +115 -59
  153. data/bin/proto/app.rb +0 -20
  154. data/bin/proto/config.rb +0 -77
  155. data/examples/blog/app.rb +0 -21
  156. data/examples/blog/config.rb +0 -95
  157. data/examples/blog/env.rb +0 -22
  158. data/examples/flash/README +0 -34
  159. data/examples/flash/app.rb +0 -20
  160. data/examples/flash/config.rb +0 -38
  161. data/examples/flash/lib/flash.rb +0 -40
  162. data/examples/flash/tmp.swf +0 -0
  163. data/examples/tiny/app.rb +0 -19
  164. data/examples/tiny/config.rb +0 -29
  165. data/examples/tiny/root/nitro-small.png +0 -0
  166. data/lib/nitro/application.rb +0 -217
  167. data/lib/nitro/config.rb +0 -128
  168. data/lib/nitro/events.rb +0 -122
  169. data/lib/nitro/html.rb +0 -151
  170. data/lib/nitro/http.rb +0 -102
  171. data/lib/nitro/l10n.rb +0 -30
  172. data/lib/nitro/server.rb +0 -59
  173. data/lib/nitro/server/appserver.rb +0 -67
  174. data/lib/nitro/server/cookie.rb +0 -87
  175. data/lib/nitro/server/dispatcher.rb +0 -62
  176. data/lib/nitro/server/filters.rb +0 -75
  177. data/lib/nitro/server/filters/autologin.rb +0 -51
  178. data/lib/nitro/server/fragment.rb +0 -70
  179. data/lib/nitro/server/handlers.rb +0 -127
  180. data/lib/nitro/server/render.rb +0 -426
  181. data/lib/nitro/server/request.rb +0 -658
  182. data/lib/nitro/server/requestpart.rb +0 -54
  183. data/lib/nitro/server/script.rb +0 -387
  184. data/lib/nitro/server/server.rb +0 -57
  185. data/lib/nitro/server/session.rb +0 -220
  186. data/lib/nitro/server/user.rb +0 -46
  187. data/lib/nitro/server/webrick.rb +0 -180
  188. data/lib/nitro/service.rb +0 -26
  189. data/lib/xsl/ui.xsl +0 -51
  190. data/lib/xsl/xforms.xsl +0 -28
  191. data/test/nitro/server/tc_cookie.rb +0 -34
  192. data/test/nitro/server/tc_filters.rb +0 -38
  193. data/test/nitro/server/tc_request.rb +0 -70
  194. data/test/nitro/server/tc_requestpart.rb +0 -28
  195. data/test/nitro/server/tc_session.rb +0 -34
  196. data/test/nitro/tc_events.rb +0 -44
  197. data/test/nitro/tc_html.rb +0 -79
  198. data/test/nitro/tc_http.rb +0 -18
@@ -4,7 +4,7 @@
4
4
  # * Elias Karakoulakis <ekarak@ktismata.com>
5
5
  #
6
6
  # (c) 2004 Navel, all rights reserved.
7
- # $Id: string.rb 165 2004-11-18 12:04:04Z gmosx $
7
+ # $Id: string.rb 202 2005-01-17 10:44:13Z gmosx $
8
8
 
9
9
  require "uri"
10
10
 
@@ -2,7 +2,7 @@
2
2
  # * George Moschovitis <gm@navel.gr>
3
3
  #
4
4
  # (c) 2004 Navel, all rights reserved.
5
- # $Id: time.rb 167 2004-11-23 14:03:10Z gmosx $
5
+ # $Id: time.rb 202 2005-01-17 10:44:13Z gmosx $
6
6
 
7
7
  require "time.rb"
8
8
 
@@ -216,7 +216,7 @@ module Validation
216
216
 
217
217
  for name in params
218
218
  confirm_name = "#{name}#{c[:postfix]}"
219
- attr_accessor :"#{confirm_name}"
219
+ eval "attr_accessor :#{confirm_name}"
220
220
 
221
221
  code = %{
222
222
  if obj.#{confirm_name}.nil? or (obj.#{confirm_name} != obj.#{name})
@@ -5,13 +5,25 @@
5
5
  # robust infrastructure for scalable web applications that can be
6
6
  # distributed over a server cluster. However, Nitro can also power
7
7
  # simple web applications for deployment on intranets or even personal
8
- # computers. Nitro integrates the powerful Og Object-Relational mapping
9
- # library.
8
+ # computers.
10
9
  #
11
- # code:
12
- # * George Moschovitis <gm@navel.gr>
10
+ # Nitro integrates the powerful Og Object-Relational mapping
11
+ # library.
13
12
  #
14
- # (c) 2004 Navel, all rights reserved.
15
- # $Id: nitro.rb 167 2004-11-23 14:03:10Z gmosx $
13
+ #--
14
+ # George Moschovitis <gm@navel.gr>
15
+ # (c) 2004-2005 Navel, all rights reserved.
16
+ # $Id: nitro.rb 215 2005-01-24 10:44:05Z gmosx $
17
+ #++
16
18
 
17
19
  require 'glue'
20
+ require 'glue/logger'
21
+
22
+ require 'nitro/context'
23
+ require 'nitro/dispatcher'
24
+ require 'nitro/render'
25
+
26
+ # Define Nitro namespace.
27
+
28
+ module Nitro
29
+ end
@@ -0,0 +1,291 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2005 Navel, all rights reserved.
3
+ # $Id$
4
+
5
+ require 'cgi'
6
+
7
+ module N
8
+
9
+ =begin
10
+ # Extend the Request module.
11
+
12
+ module Request
13
+ include CGI::QueryExtension
14
+
15
+ def stdinput
16
+ @in
17
+ end
18
+ end
19
+ =end
20
+
21
+ # CGI utility methods.
22
+
23
+ class CgiUtils
24
+
25
+ # HTTP protocol EOL constants
26
+
27
+ CR = "\x0d"
28
+ LF = "\x0a"
29
+ CRLF = "\x0d\x0a"
30
+ EOL = CRLF
31
+
32
+ # Constants for readable code
33
+
34
+ STATUS_OK = 200
35
+ STATUS_PARTIAL_CONTENT = 206
36
+ STATUS_MOVED = 301
37
+ STATUS_REDIRECT = 302
38
+ STATUS_SEE_OTHER = 303 # gmosx: VERIFY THIS
39
+ STATUS_SEE_OTHER_307 = 307 # gmosx: VERIFY THIS
40
+ STATUS_NOT_MODIFIED = 304
41
+ STATUS_BAD_REQUEST = 400
42
+ STATUS_AUTH_REQUIRED = 401
43
+ STATUS_FORBIDDEN = 403
44
+ STATUS_NOT_FOUND = 404
45
+ STATUS_METHOD_NOT_ALLOWED = 405
46
+ STATUS_NOT_ACCEPTABLE = 406
47
+ STATUS_LENGTH_REQUIRED = 411
48
+ STATUS_PRECONDITION_FAILED = 412
49
+ STATUS_SERVER_ERROR = 500
50
+ STATUS_NOT_IMPLEMENTED = 501
51
+ STATUS_BAD_GATEWAY = 502
52
+ STATUS_VARIANT_ALSO_VARIES = 506
53
+
54
+ # Hash to allow id to description maping.
55
+
56
+ STATUS_STRINGS = {
57
+ 200 => "OK",
58
+ 206 => "Partial Content",
59
+ 300 => "Multiple Choices",
60
+ 301 => "Moved Permanently",
61
+ 302 => "Found",
62
+ 303 => "See other", # gmosx: VERIFY THIS
63
+ 304 => "Not Modified",
64
+ 307 => "See other 07", # gmosx: VERIFY THIS
65
+ 400 => "Bad Request",
66
+ 401 => "Authorization Required",
67
+ 403 => "Forbidden",
68
+ 404 => "Not Found",
69
+ 405 => "Method Not Allowed",
70
+ 406 => "Not Acceptable",
71
+ 411 => "Length Required",
72
+ 412 => "Precondition Failed",
73
+ 500 => "Internal Server Error",
74
+ 501 => "Method Not Implemented",
75
+ 502 => "Bad Gateway",
76
+ 506 => "Variant Also Negotiates"
77
+ }
78
+
79
+ # Returns a hash with the pairs from the query
80
+ # string. The implicit hash construction that is done
81
+ # in parse_request_params is not done here.
82
+ #
83
+ # Parameters in the form xxx[] are converted
84
+ # to arrays.
85
+
86
+ def self.parse_query_string(query_string)
87
+ # gmosx, THINK: better return nil here?
88
+
89
+ return {} if (query_string.nil? or query_string.empty?)
90
+
91
+ params = {}
92
+
93
+ query_string.split(/[&;]/).each do |p|
94
+ key, val = p.split('=')
95
+
96
+ key = CGI.unescape(key) unless key.nil?
97
+ val = CGI.unescape(val) unless val.nil?
98
+
99
+ if key =~ /(.*)\[\]$/
100
+ if params.has_key?($1)
101
+ params[$1] << val
102
+ else
103
+ params[$1] = [val]
104
+ end
105
+ else
106
+ params[key] = val.nil? ? nil : val
107
+ end
108
+ end
109
+
110
+ return params
111
+ end
112
+
113
+ # Parse the HTTP_COOKIE header and returns the
114
+ # cookies as a key->value hash. For efficiency no
115
+ # cookie objects are created.
116
+ #
117
+ # [+context+]
118
+ # The context
119
+
120
+ def self.parse_cookies(context)
121
+ env = context.env
122
+
123
+ # FIXME: dont precreate?
124
+ context.cookies = {}
125
+
126
+ if env.has_key?('HTTP_COOKIE') or env.has_key?('COOKIE')
127
+ (env['HTTP_COOKIE'] or env['COOKIE']).split(/; /).each do |c|
128
+ key, val = c.split(/=/, 2)
129
+
130
+ key = CGI.unescape(key)
131
+ val = val.split(/&/).collect{|v| CGI::unescape(v)}.join("\0")
132
+
133
+ if context.cookies.include?(key)
134
+ context.cookies[key] += "\0" + val
135
+ else
136
+ context.cookies[key] = val
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ # Build the response headers for the context.
143
+
144
+ def self.response_headers(context)
145
+ reason = STATUS_STRINGS[context.status]
146
+ buf = "HTTP/1.1 #{context.status} #{reason} #{EOL}"
147
+
148
+ context.response_headers.each do |key, value|
149
+ tmp = key.gsub(/\bwww|^te$|\b\w/) { |s| s.upcase }
150
+ buf << "#{tmp}: #{value}" << EOL
151
+ end
152
+
153
+ context.response_cookies.each do |cookie|
154
+ buf << "Set-Cookie: " << cookie.to_s << EOL
155
+ end if context.response_cookies
156
+
157
+ buf << EOL
158
+ end
159
+
160
+ # Initialize the request params.
161
+ # Handles multipart forms (in particular, forms that involve
162
+ # file uploads). Reads query parameters in the @params field,
163
+ # and cookies into @cookies.
164
+
165
+ def self.parse_params(context)
166
+ method = context.method
167
+ if (:post == method) and
168
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n.match(context.headers['CONTENT_TYPE'])
169
+ boundary = $1.dup
170
+ context.params = read_multipart(boundary, Integer(context.headers['CONTENT_LENGTH']))
171
+ else
172
+ case method
173
+ when :get, :head
174
+ context.params = CgiUtils.parse_query_string(context.query_string)
175
+ when :post
176
+ context.in.binmode if defined?(context.in.binmode)
177
+
178
+ context.params = CgiUtils.parse_query_string(
179
+ context.in.read(
180
+ Integer(context.headers['CONTENT_LENGTH'])) || '')
181
+ end
182
+ end
183
+ end
184
+
185
+ # Parse a multipart request.
186
+
187
+ def self.read_multipart(boundary, content_length)
188
+ params = Hash.new([])
189
+ boundary = "--" + boundary
190
+ buf = ""
191
+ bufsize = 10 * 1024
192
+
193
+ # start multipart/form-data
194
+ stdinput.binmode if defined? stdinput.binmode
195
+ boundary_size = boundary.size + EOL.size
196
+ content_length -= boundary_size
197
+ status = stdinput.read(boundary_size)
198
+ if nil == status
199
+ raise EOFError, "no content body"
200
+ elsif boundary + EOL != status
201
+ raise EOFError, "bad content body"
202
+ end
203
+
204
+ loop do
205
+ head = nil
206
+ if 10240 < content_length
207
+ require "tempfile"
208
+ body = Tempfile.new("CGI")
209
+ else
210
+ begin
211
+ require "stringio"
212
+ body = StringIO.new
213
+ rescue LoadError
214
+ require "tempfile"
215
+ body = Tempfile.new("CGI")
216
+ end
217
+ end
218
+ body.binmode if defined? body.binmode
219
+
220
+ until head and /#{boundary}(?:#{EOL}|--)/n.match(buf)
221
+
222
+ if (not head) and /#{EOL}#{EOL}/n.match(buf)
223
+ buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/n) do
224
+ head = $1.dup
225
+ ""
226
+ end
227
+ next
228
+ end
229
+
230
+ if head and ( (EOL + boundary + EOL).size < buf.size )
231
+ body.print buf[0 ... (buf.size - (EOL + boundary + EOL).size)]
232
+ buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = ""
233
+ end
234
+
235
+ c = if bufsize < content_length
236
+ stdinput.read(bufsize)
237
+ else
238
+ stdinput.read(content_length)
239
+ end
240
+ if c.nil?
241
+ raise EOFError, "bad content body"
242
+ end
243
+ buf.concat(c)
244
+ content_length -= c.size
245
+ end
246
+
247
+ buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{boundary}([\r\n]{1,2}|--)/n) do
248
+ body.print $1
249
+ if "--" == $2
250
+ content_length = -1
251
+ end
252
+ ""
253
+ end
254
+
255
+ body.rewind
256
+
257
+ /Content-Disposition:.* filename="?([^\";]*)"?/ni.match(head)
258
+ filename = ($1 or "")
259
+ if /Mac/ni.match(env_table['HTTP_USER_AGENT']) and
260
+ /Mozilla/ni.match(env_table['HTTP_USER_AGENT']) and
261
+ (not /MSIE/ni.match(env_table['HTTP_USER_AGENT']))
262
+ filename = CGI::unescape(filename)
263
+ end
264
+
265
+ /Content-Type: (.*)/ni.match(head)
266
+ content_type = ($1 or "")
267
+
268
+ (class << body; self; end).class_eval do
269
+ alias local_path path
270
+ define_method(:original_filename) {filename.dup.taint}
271
+ define_method(:content_type) {content_type.dup.taint}
272
+ end
273
+
274
+ /Content-Disposition:.* name="?([^\";]*)"?/ni.match(head)
275
+ name = $1.dup
276
+
277
+ if params.has_key?(name)
278
+ params[name].push(body)
279
+ else
280
+ params[name] = [body]
281
+ end
282
+ break if buf.size == 0
283
+ break if content_length === -1
284
+ end
285
+
286
+ params
287
+ end
288
+
289
+ end
290
+
291
+ end
@@ -0,0 +1,42 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2005 Navel, all rights reserved.
3
+ # $Id$
4
+
5
+ require 'cgi'
6
+ require 'fcgi'
7
+
8
+ require 'nitro/context'
9
+ require 'nitro/dispatcher'
10
+ require 'nitro/adaptors/cgi'
11
+
12
+ module N
13
+
14
+ # FastCGI Adaptor. FastCGI is a language independent,
15
+ # scalable, open extension to CGI that provides high
16
+ # performance without the limitations of server
17
+ # specific APIs.
18
+
19
+ class FastCGI
20
+
21
+ def self.start(conf)
22
+ FCGI.each do |cgi|
23
+ context = Context.new(conf)
24
+
25
+ context.in = cgi.in
26
+ context.headers = cgi.env
27
+
28
+ CgiUtils.parse_params(context)
29
+ CgiUtils.parse_cookies(context)
30
+
31
+ context.render(context.path)
32
+
33
+ cgi.out.print(CgiUtils.response_headers(context))
34
+ cgi.out.print(context.out)
35
+
36
+ cgi.finish
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # * George Moschovitis <gm@navel.gr>
4
+ # (c) 2004-2005 Navel, all rights reserved.
5
+ # $Id$
6
+
7
+ require 'optparse'
8
+
9
+ module N
10
+
11
+ # The Runner is a helper class that encapsulates a web
12
+ # application and is responsible for launching the
13
+ # application using different adaptors. Default arguments
14
+ # parsing is also provided.
15
+ #
16
+ # You can implement your own, custom version of the Runner
17
+ # to run your custom web applications.
18
+ #
19
+ #--
20
+ # TODO: find a better name
21
+ #++
22
+
23
+ class Runner
24
+
25
+ # Parse the arguments and run the web application
26
+ # using the declared environment and adaptor
27
+
28
+ def self.run(argv)
29
+
30
+ # :start, :stop, :restart.
31
+
32
+ action = :start
33
+
34
+ # :webrick, :lhttp, :apache
35
+
36
+ server = :webrick
37
+
38
+ # daemonize? (in webrick only)
39
+
40
+ daemon = false
41
+
42
+ # log to file ?
43
+
44
+ log_to_file = false
45
+
46
+ # Parse the arguments.
47
+
48
+ parser = OptionParser.new do |opts|
49
+
50
+ opts.banner = 'Usage: ctl [options]'
51
+ opts.separator ''
52
+ opts.separator 'Specific options:'
53
+
54
+ opts.on("-s", "--start", "Start application.") do
55
+ action = :start
56
+ end
57
+
58
+ opts.on("-S", "--stop", "Stop application.") do
59
+ action = :stop
60
+ end
61
+
62
+ opts.on("-r", "--restart", "Restart application.") do
63
+ action = :restart
64
+ end
65
+
66
+ opts.on("-d", "--daemon", "Run application as a daemon.") do
67
+ daemon = true
68
+ log_to_file = true
69
+ end
70
+
71
+ opts.on("-D", "--debug", "Run application in debug mode.") do
72
+ $DBG = true
73
+ end
74
+
75
+ opts.on("-w", "--webrick", "Use a webrick server [default].") do
76
+ server = :webrick
77
+ end
78
+
79
+ opts.on("-l", "--lhttpd", "Use a webrick server [default].") do
80
+ server = :lhttpd
81
+ log_to_file = true
82
+ end
83
+
84
+ opts.on_tail("-v", "--version", "Show version.") do
85
+ require 'nitro/version'
86
+ puts "Nitro #{Nitro::Version}"
87
+ exit
88
+ end
89
+
90
+ opts.on_tail("-?", "--help", "Show this message.") do
91
+ puts opts
92
+ exit
93
+ end
94
+
95
+ end
96
+
97
+ parser.parse!(ARGV)
98
+
99
+ require 'conf/app.conf.rb'
100
+
101
+ if log_to_file
102
+ Logger.set(Logger.new('log/app.log'))
103
+ end
104
+
105
+ case server
106
+
107
+ when :webrick
108
+ require 'nitro/adaptors/webrick'
109
+ N::Webrick.start($conf)
110
+
111
+ when :lhttpd
112
+ require 'nitro/adaptors/fastcgi'
113
+ `lighttpd -f conf/lhttpd.conf`
114
+ end
115
+ end
116
+
117
+ end
118
+
119
+ # Run the app!
120
+
121
+ Runner.run(ARGV)
122
+
123
+ end