nitro 0.13.0 → 0.14.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 (64) hide show
  1. data/CHANGELOG +91 -1632
  2. data/INSTALL +44 -0
  3. data/README +1 -1
  4. data/Rakefile +3 -3
  5. data/doc/CHANGELOG.2 +1688 -0
  6. data/doc/RELEASES +84 -1
  7. data/examples/blog/cache/entriesadmin +12 -0
  8. data/examples/blog/conf/apache.conf.new +53 -0
  9. data/examples/blog/conf/lhttpd.conf +23 -180
  10. data/examples/blog/log/apache.error_log +271 -0
  11. data/examples/blog/log/rewrite_log +161 -0
  12. data/examples/blog/public/fcgi.rb +2 -0
  13. data/examples/blog/run.rb +4 -3
  14. data/examples/blog/src/controller.rb +10 -4
  15. data/examples/blog/src/views/index.xhtml +3 -0
  16. data/examples/blog/src/xsl/base.xsl +7 -0
  17. data/examples/no_xsl_blog/conf/lhttpd.conf +24 -181
  18. data/examples/tiny/conf/lhttpd.conf +24 -181
  19. data/examples/tiny/log/apache.error_log +24 -0
  20. data/examples/tiny/public/index.xhtml +0 -6
  21. data/examples/tiny/public/upload.xhtml +12 -14
  22. data/examples/wee_style/run.rb +2 -0
  23. data/examples/why_wiki/run.rb +2 -0
  24. data/lib/nitro.rb +2 -2
  25. data/lib/nitro/adapters/cgi.rb +36 -109
  26. data/lib/nitro/adapters/webrick.rb +76 -62
  27. data/lib/nitro/caching.rb +29 -0
  28. data/lib/nitro/caching/actions.rb +67 -0
  29. data/lib/nitro/caching/fragments.rb +72 -0
  30. data/lib/nitro/caching/invalidation.rb +51 -0
  31. data/lib/nitro/caching/output.rb +72 -0
  32. data/lib/nitro/caching/stores.rb +84 -0
  33. data/lib/nitro/controller.rb +3 -1
  34. data/lib/nitro/dispatcher.rb +0 -1
  35. data/lib/nitro/filters.rb +112 -55
  36. data/lib/nitro/mail.rb +6 -3
  37. data/lib/nitro/render.rb +27 -4
  38. data/lib/nitro/request.rb +13 -1
  39. data/test/nitro/tc_controller.rb +6 -4
  40. data/test/nitro/tc_filters.rb +111 -0
  41. metadata +19 -29
  42. data/examples/why_wiki/wiki.yml +0 -1
  43. data/vendor/README +0 -11
  44. data/vendor/binding_of_caller.rb +0 -81
  45. data/vendor/blankslate.rb +0 -53
  46. data/vendor/breakpoint.rb +0 -523
  47. data/vendor/breakpoint_client.rb +0 -196
  48. data/vendor/extensions/_base.rb +0 -153
  49. data/vendor/extensions/_template.rb +0 -36
  50. data/vendor/extensions/all.rb +0 -21
  51. data/vendor/extensions/array.rb +0 -68
  52. data/vendor/extensions/binding.rb +0 -224
  53. data/vendor/extensions/class.rb +0 -50
  54. data/vendor/extensions/continuation.rb +0 -71
  55. data/vendor/extensions/enumerable.rb +0 -250
  56. data/vendor/extensions/hash.rb +0 -23
  57. data/vendor/extensions/io.rb +0 -58
  58. data/vendor/extensions/kernel.rb +0 -42
  59. data/vendor/extensions/module.rb +0 -114
  60. data/vendor/extensions/numeric.rb +0 -230
  61. data/vendor/extensions/object.rb +0 -164
  62. data/vendor/extensions/ostruct.rb +0 -41
  63. data/vendor/extensions/string.rb +0 -316
  64. data/vendor/extensions/symbol.rb +0 -28
@@ -3,44 +3,24 @@
3
3
  # $Id$
4
4
 
5
5
  require 'webrick'
6
+ require 'stringio'
6
7
 
7
8
  require 'glue/flexob'
8
-
9
9
  require 'nitro/context'
10
10
  require 'nitro/dispatcher'
11
11
 
12
- module WEBrick
13
-
14
- class HTTPRequest
15
- attr :socket
16
- end
17
-
18
- class HTTPResponse
19
- def header=(header)
20
- @header = header
21
- end
22
-
23
- def cookies=(cookies)
24
- @cookies = cookies
25
- end
26
- end
27
-
28
- end
29
-
30
12
  module N
31
13
 
32
14
  # Helper methods for the WebrickAdapter.
33
15
 
34
16
  class Webrick
35
-
17
+
36
18
  class << self
37
19
  attr_accessor :server
38
20
 
39
21
  def start(conf)
40
22
  conf = Conf.new(conf) unless conf.is_a?(Conf)
41
23
 
42
- # patch for OSX
43
-
44
24
  Socket.do_not_reverse_lookup = true
45
25
 
46
26
  if :none == conf.log and RUBY_PLATFORM !~ /mswin32/
@@ -80,6 +60,7 @@ end
80
60
  #++
81
61
 
82
62
  class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
63
+ include WEBrick
83
64
 
84
65
  # REQUEST_MUTEX = Mutex.new
85
66
 
@@ -89,60 +70,93 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
89
70
  # Handles static resources. Useful when running
90
71
  # a stand-alone webrick server.
91
72
 
92
- @file_handler = WEBrick::HTTPServlet::FileHandler.new(
93
- server,
94
- conf.dispatcher.public_root, conf.webrick_options || {})
73
+ @file_handler = WEBrick::HTTPServlet::FileHandler.new(server, conf.dispatcher.public_root, conf.webrick_options || {})
95
74
  end
96
-
97
- def handle(req, res)
98
- path = req.request_uri.path
99
75
 
100
- if path =~ /\./
76
+ # Handle a static file. Also handles cached pages.
77
+
78
+ def handle_file(req, res)
79
+ begin
80
+ rewrite(req)
101
81
  @file_handler.do_GET(req, res)
102
- else
103
- # gmosx, TODO: move this into a filter.
104
- Og.db.get_connection if defined?(Og) and Og.db
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
105
92
 
106
- # REQUEST_MUTEX.lock
93
+ # Handle the request.
107
94
 
108
- context = Context.new(@conf)
109
-
110
- context.headers = {}
111
- req.header.each { |h, v| context.headers[h.upcase] = v.first }
112
- context.headers.update(req.meta_vars)
113
-
114
- context.params = {}
115
- req.query.each do |k, v|
116
- if k =~ /(.*)\[\]$/
117
- context.params[k] = v
118
- else
119
- context.params[k] = v.to_s
120
- end
121
- end
122
- # context.in = req.socket
123
- # CgiUtils.parse_params(context)
95
+ def handle(req, res)
96
+ unless handle_file(req, res)
97
+ path = req.request_uri.path
124
98
 
125
- #context.cookies = {}
126
- #req.cookies.each { |c| context.cookies[c.name] = c.value }
127
- CgiUtils.parse_cookies(context)
99
+ unless path =~ /\./
100
+ begin
101
+ path = req.request_uri.path
128
102
 
129
- context.render(path)
130
-
131
- res.status = context.status
132
- res.header = context.response_headers || {}
133
- res.cookies = context.response_cookies || {}
134
- res.body = context.out
103
+ # gmosx, TODO: move this into a filter.
104
+ Og.db.get_connection if defined?(Og) and Og.db
105
+
106
+ # REQUEST_MUTEX.lock
107
+
108
+ context = Context.new(@conf)
109
+
110
+ context.in = StringIO.new(req.body || "")
111
+
112
+ context.headers = {}
113
+ req.header.each { |h, v| context.headers[h.upcase] = v.first }
114
+ context.headers.update(req.meta_vars)
115
+ # gmosx: make compatible with fastcgi.
116
+ context.headers['REQUEST_URI'].slice!(/http:\/\/(.*)\//)
117
+ context.headers['REQUEST_URI'] << '/'
118
+
119
+ CgiUtils.parse_params(context)
120
+ CgiUtils.parse_cookies(context)
135
121
 
136
- context.close
122
+ context.render(path)
123
+
124
+ res.status = context.status
125
+ res.instance_variable_set(:@header, context.response_headers || {})
126
+ res.instance_variable_set(:@cookies, context.response_cookies || {})
127
+ res.body = context.out
128
+
129
+ context.close
130
+ ensure
131
+ # REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked?
132
+ Og.db.put_connection if defined?(Og) and Og.db
133
+ end
134
+ end
137
135
  end
138
- ensure
139
- # REQUEST_MUTEX.unlock if REQUEST_MUTEX.locked?
140
- Og.db.put_connection if defined?(Og) and Og.db
141
136
  end
142
137
 
143
138
  alias do_GET handle
144
139
  alias do_POST handle
145
140
 
141
+ # Try to rewrite the path to a filename.
142
+
143
+ def rewrite(req)
144
+ if req.path == '/'
145
+ req.instance_variable_set(:@path_info, '/index.html')
146
+ elsif req.path =~ /^([^.]+)$/
147
+ req.instance_variable_set(:@path_info, "#{$1}.html")
148
+ end
149
+ end
150
+
151
+ # Rewrite back to the original path.
152
+
153
+ def unrewrite(req)
154
+ if req.path == '/'
155
+ req.instance_variable_set(:@path_info, '/')
156
+ elsif req.path =~ /^([^.]+).html$/
157
+ req.instance_variable_set(:@path_info, $1)
158
+ end
159
+ end
146
160
  end
147
161
 
148
162
  end
@@ -0,0 +1,29 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: caching.rb 326 2005-03-28 11:07:17Z gmosx $
4
+
5
+ require 'fileutils'
6
+
7
+ require 'glue/attribute'
8
+
9
+ require 'nitro/caching/output'
10
+ require 'nitro/caching/actions'
11
+ require 'nitro/caching/fragments'
12
+
13
+ module N
14
+
15
+ # Adds support for caching.
16
+
17
+ module Caching
18
+
19
+ def self.append_features(base) #:nodoc:
20
+ super
21
+ base.send :include, Output, Actions, Fragments
22
+ base.class_eval do
23
+ cattr_accessor :caching_enabled, true
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,67 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: actions.rb 326 2005-03-28 11:07:17Z gmosx $
4
+
5
+ require 'fileutils'
6
+
7
+ module N
8
+
9
+ # Adds support for caching.
10
+
11
+ module Caching
12
+
13
+ # Action caching.
14
+
15
+ module Actions
16
+
17
+ def self.append_features(base) # :nodoc:
18
+ super
19
+ base.extend(ClassMethods)
20
+ end
21
+
22
+ module ClassMethods
23
+
24
+ def cache_action(*actions)
25
+ return unless caching_enabled
26
+
27
+ before_filter(
28
+ %{
29
+ fragment_name = "\#\{@action_name\}\#{@request.query_string}"
30
+ if fragment = Fragment.get(fragment_name)
31
+ @out = fragment
32
+ return
33
+ end
34
+ },
35
+ :only => actions
36
+ )
37
+
38
+ after_filter(
39
+ %{
40
+ fragment_name = "\#\{@action_name\}\#{@request.query_string}"
41
+ Fragment.put(fragment_name, @out)
42
+ },
43
+ :only => actions
44
+ )
45
+ end
46
+
47
+ end
48
+
49
+ private
50
+
51
+ #--
52
+ # FIXME: not implemented.
53
+ #++
54
+
55
+ def expire_action(*actions)
56
+ return unless caching_enabled
57
+
58
+ for action in [actions].flatten
59
+ expire_fragment(action)
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,72 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: fragments.rb 326 2005-03-28 11:07:17Z gmosx $
4
+
5
+ require 'fileutils'
6
+
7
+ require 'glue/attribute'
8
+ require 'nitro/caching/stores'
9
+
10
+ module N
11
+
12
+ # Adds support for caching.
13
+
14
+ module Caching
15
+
16
+ # Action caching.
17
+
18
+ module Fragments
19
+
20
+ @@store = FileStore.new # MemoryStore.new
21
+
22
+ def self.store
23
+ @@store
24
+ end
25
+
26
+ def self.store=(store)
27
+ @@store = store
28
+ end
29
+
30
+ def self.get(name, options = {})
31
+ return @@store.read(name, options)
32
+ end
33
+
34
+ def self.put(name, content = nil, options = {})
35
+ @@store.write(name, content, options)
36
+ return content
37
+ end
38
+
39
+ def self.append_features(base) # :nodoc:
40
+ super
41
+ end
42
+
43
+ private
44
+
45
+ def cache(name = nil, options = {}, &block)
46
+ name = @action_name unless name
47
+ cache_fragment(block, "#{name}#{options}", options)
48
+ end
49
+
50
+ def cache_fragment(block, name, options = {})
51
+ unless caching_enabled
52
+ block.call
53
+ return
54
+ end
55
+
56
+ if fragment = Fragments.get(name, options)
57
+ @out << fragment
58
+ else
59
+ pos = @out.length
60
+ block.call
61
+ Fragments.put(name, @out[pos..-1], options)
62
+ end
63
+ end
64
+
65
+ def expire_fragment(name, options = {})
66
+ Fragments.store.delete(name, options)
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,51 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: invalidation.rb 327 2005-03-28 11:09:58Z gmosx $
4
+
5
+ module N
6
+
7
+ module Caching
8
+
9
+ # Support for invalidating output/fragment caches.
10
+
11
+ module Invalidation
12
+
13
+ def self.append_features(base) #:nodoc:
14
+ super
15
+ base.extend(ClassMethods)
16
+ end
17
+
18
+ module ClassMethods
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+
28
+ __END__
29
+
30
+ class MyController < Controller
31
+
32
+ cache_output :list
33
+
34
+ cache_monitor :on => [ :add, :delete ]
35
+
36
+ def list
37
+ end
38
+
39
+ def add
40
+ end
41
+
42
+ def delete
43
+ end
44
+
45
+ end
46
+
47
+ class Invalidator
48
+ def filter(controller)
49
+
50
+ end
51
+ end
@@ -0,0 +1,72 @@
1
+ # * George Moschovitis <gm@navel.gr>
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: output.rb 322 2005-03-21 18:15:52Z gmosx $
4
+
5
+ require 'fileutils'
6
+
7
+ module N
8
+
9
+ # Adds support for caching.
10
+
11
+ module Caching
12
+
13
+ # Output caching.
14
+
15
+ module Output
16
+
17
+ def self.append_features(base) # :nodoc:
18
+ super
19
+ base.extend(ClassMethods)
20
+ base.module_eval do
21
+ cattr_accessor :output_cache_root, 'public'
22
+ end
23
+ end
24
+
25
+ module ClassMethods
26
+
27
+ def do_cache_output(path, content)
28
+ filepath = output_cache_path(path)
29
+ FileUtils.makedirs(File.dirname(filepath))
30
+ File.open(filepath, 'w+') { |f| f.write(content) }
31
+ Logger.debug "Cached page: #{filepath}" if $DBG
32
+ end
33
+
34
+ # Enable output caching for the given actions.
35
+
36
+ def cache_output(*actions)
37
+ return unless caching_enabled
38
+
39
+ str = actions.collect { |a| ":#{a}" }.join(', ')
40
+
41
+ module_eval %{
42
+ after_filter "do_cache_output", :only => [ #{str} ]
43
+ }
44
+ end
45
+
46
+ private
47
+
48
+ def output_cache_path(path)
49
+ filename = ((path.empty? || path == '/') ? '/index' : path)
50
+ filename << '.html' unless (name.split('/').last || name).include? '.'
51
+ return output_cache_root + filename
52
+ end
53
+
54
+ end
55
+
56
+ private
57
+
58
+ def do_cache_output
59
+ if caching_enabled and caching_allowed?
60
+ self.class.do_cache_output(@request.path, @out)
61
+ end
62
+ end
63
+
64
+ def caching_allowed?
65
+ !@request.post?
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end