mongrel_esi 0.4.1 → 0.5.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 (184) hide show
  1. data/Rakefile +15 -8
  2. data/bin/mongrel_esi +0 -0
  3. data/ext/esi/common.rl +32 -27
  4. data/ext/esi/esi_parser.c +11 -4
  5. data/ext/esi/parser.c +4536 -901
  6. data/ext/esi/parser.h +7 -0
  7. data/ext/esi/parser.rl +171 -53
  8. data/ext/esi/run-test.rb +0 -0
  9. data/ext/esi/test/common.rl +32 -27
  10. data/ext/esi/test/parser.c +322 -1342
  11. data/ext/esi/test/parser.h +7 -0
  12. data/ext/esi/test/parser.rl +171 -53
  13. data/ext/esi/test/test.c +13 -4
  14. data/ext/esi/test1.rb +35 -3
  15. data/lib/esi/cache.rb +2 -1
  16. data/lib/esi/config.rb +37 -0
  17. data/lib/esi/dispatcher.rb +3 -5
  18. data/lib/esi/invalidator.rb +3 -0
  19. data/lib/esi/logger.rb +0 -7
  20. data/lib/esi/parser.rb +70 -0
  21. data/lib/esi/processor.rb +88 -0
  22. data/lib/esi/proxy.rb +104 -0
  23. data/lib/esi/response.rb +106 -0
  24. data/lib/esi/router.rb +3 -0
  25. data/lib/esi/tag/attempt.rb +3 -0
  26. data/lib/esi/tag/base.rb +3 -1
  27. data/lib/esi/tag/except.rb +2 -0
  28. data/lib/esi/tag/include.rb +131 -132
  29. data/lib/esi/tag/invalidate.rb +2 -0
  30. data/lib/esi/tag/try.rb +3 -0
  31. data/test/integration/basic_test.rb +0 -1
  32. data/test/integration/docs/esi_max_age_varies.html +10 -0
  33. data/test/integration/handler_test.rb +31 -5
  34. data/test/integration/help.rb +13 -1
  35. data/test/load_test.rb +133 -0
  36. data/test/unit/include_request_test.rb +1 -1
  37. data/test/unit/parser_test.rb +41 -5
  38. data/test/unit/response_test.rb +184 -0
  39. metadata +50 -224
  40. data/doc/rdoc/classes/ESI/Cache.html +0 -178
  41. data/doc/rdoc/classes/ESI/Cache.src/M000060.html +0 -17
  42. data/doc/rdoc/classes/ESI/Cache.src/M000061.html +0 -20
  43. data/doc/rdoc/classes/ESI/Config/CacheConfig.html +0 -212
  44. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000055.html +0 -19
  45. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000056.html +0 -19
  46. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000057.html +0 -18
  47. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000058.html +0 -18
  48. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000059.html +0 -18
  49. data/doc/rdoc/classes/ESI/Config/ConfigRouter.html +0 -187
  50. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000052.html +0 -19
  51. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000053.html +0 -21
  52. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000054.html +0 -21
  53. data/doc/rdoc/classes/ESI/Config.html +0 -291
  54. data/doc/rdoc/classes/ESI/Config.src/M000043.html +0 -18
  55. data/doc/rdoc/classes/ESI/Config.src/M000044.html +0 -18
  56. data/doc/rdoc/classes/ESI/Config.src/M000045.html +0 -35
  57. data/doc/rdoc/classes/ESI/Config.src/M000046.html +0 -38
  58. data/doc/rdoc/classes/ESI/Config.src/M000047.html +0 -23
  59. data/doc/rdoc/classes/ESI/Config.src/M000048.html +0 -18
  60. data/doc/rdoc/classes/ESI/Config.src/M000049.html +0 -20
  61. data/doc/rdoc/classes/ESI/Config.src/M000050.html +0 -18
  62. data/doc/rdoc/classes/ESI/Config.src/M000051.html +0 -24
  63. data/doc/rdoc/classes/ESI/Dispatcher.html +0 -172
  64. data/doc/rdoc/classes/ESI/Dispatcher.src/M000062.html +0 -23
  65. data/doc/rdoc/classes/ESI/Dispatcher.src/M000063.html +0 -20
  66. data/doc/rdoc/classes/ESI/Fragment.html +0 -218
  67. data/doc/rdoc/classes/ESI/Fragment.src/M000076.html +0 -21
  68. data/doc/rdoc/classes/ESI/Fragment.src/M000077.html +0 -18
  69. data/doc/rdoc/classes/ESI/Fragment.src/M000078.html +0 -18
  70. data/doc/rdoc/classes/ESI/Handler.html +0 -236
  71. data/doc/rdoc/classes/ESI/Handler.src/M000079.html +0 -19
  72. data/doc/rdoc/classes/ESI/Handler.src/M000080.html +0 -161
  73. data/doc/rdoc/classes/ESI/Handler.src/M000081.html +0 -24
  74. data/doc/rdoc/classes/ESI/Handler.src/M000082.html +0 -18
  75. data/doc/rdoc/classes/ESI/Handler.src/M000083.html +0 -26
  76. data/doc/rdoc/classes/ESI/Handler.src/M000084.html +0 -30
  77. data/doc/rdoc/classes/ESI/Invalidator.html +0 -131
  78. data/doc/rdoc/classes/ESI/Invalidator.src/M000004.html +0 -41
  79. data/doc/rdoc/classes/ESI/Log.html +0 -251
  80. data/doc/rdoc/classes/ESI/Log.src/M000005.html +0 -18
  81. data/doc/rdoc/classes/ESI/Log.src/M000006.html +0 -18
  82. data/doc/rdoc/classes/ESI/Log.src/M000007.html +0 -18
  83. data/doc/rdoc/classes/ESI/Log.src/M000008.html +0 -18
  84. data/doc/rdoc/classes/ESI/Log.src/M000009.html +0 -18
  85. data/doc/rdoc/classes/ESI/Log.src/M000010.html +0 -18
  86. data/doc/rdoc/classes/ESI/Log.src/M000011.html +0 -18
  87. data/doc/rdoc/classes/ESI/Log.src/M000012.html +0 -18
  88. data/doc/rdoc/classes/ESI/Log.src/M000013.html +0 -18
  89. data/doc/rdoc/classes/ESI/MemcachedCache.html +0 -314
  90. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000034.html +0 -24
  91. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000035.html +0 -22
  92. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000036.html +0 -19
  93. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000037.html +0 -23
  94. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000038.html +0 -18
  95. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000039.html +0 -19
  96. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000040.html +0 -18
  97. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000041.html +0 -18
  98. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000042.html +0 -17
  99. data/doc/rdoc/classes/ESI/Router.html +0 -229
  100. data/doc/rdoc/classes/ESI/Router.src/M000073.html +0 -36
  101. data/doc/rdoc/classes/ESI/Router.src/M000074.html +0 -25
  102. data/doc/rdoc/classes/ESI/Router.src/M000075.html +0 -24
  103. data/doc/rdoc/classes/ESI/RubyCache.html +0 -278
  104. data/doc/rdoc/classes/ESI/RubyCache.src/M000064.html +0 -20
  105. data/doc/rdoc/classes/ESI/RubyCache.src/M000065.html +0 -22
  106. data/doc/rdoc/classes/ESI/RubyCache.src/M000066.html +0 -21
  107. data/doc/rdoc/classes/ESI/RubyCache.src/M000067.html +0 -22
  108. data/doc/rdoc/classes/ESI/RubyCache.src/M000068.html +0 -18
  109. data/doc/rdoc/classes/ESI/RubyCache.src/M000069.html +0 -22
  110. data/doc/rdoc/classes/ESI/RubyCache.src/M000070.html +0 -18
  111. data/doc/rdoc/classes/ESI/RubyCache.src/M000071.html +0 -18
  112. data/doc/rdoc/classes/ESI/RubyCache.src/M000072.html +0 -18
  113. data/doc/rdoc/classes/ESI/Tag/Attempt.html +0 -113
  114. data/doc/rdoc/classes/ESI/Tag/Base.html +0 -267
  115. data/doc/rdoc/classes/ESI/Tag/Base.src/M000028.html +0 -26
  116. data/doc/rdoc/classes/ESI/Tag/Base.src/M000029.html +0 -23
  117. data/doc/rdoc/classes/ESI/Tag/Base.src/M000030.html +0 -22
  118. data/doc/rdoc/classes/ESI/Tag/Base.src/M000031.html +0 -18
  119. data/doc/rdoc/classes/ESI/Tag/Base.src/M000032.html +0 -22
  120. data/doc/rdoc/classes/ESI/Tag/Base.src/M000033.html +0 -23
  121. data/doc/rdoc/classes/ESI/Tag/Except.html +0 -184
  122. data/doc/rdoc/classes/ESI/Tag/Except.src/M000020.html +0 -21
  123. data/doc/rdoc/classes/ESI/Tag/Except.src/M000021.html +0 -20
  124. data/doc/rdoc/classes/ESI/Tag/Except.src/M000022.html +0 -18
  125. data/doc/rdoc/classes/ESI/Tag/Include.html +0 -189
  126. data/doc/rdoc/classes/ESI/Tag/Include.src/M000017.html +0 -20
  127. data/doc/rdoc/classes/ESI/Tag/Include.src/M000018.html +0 -18
  128. data/doc/rdoc/classes/ESI/Tag/Include.src/M000019.html +0 -125
  129. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.html +0 -155
  130. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.src/M000016.html +0 -19
  131. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.html +0 -199
  132. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000014.html +0 -18
  133. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000015.html +0 -42
  134. data/doc/rdoc/classes/ESI/Tag/Invalidate.html +0 -171
  135. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000025.html +0 -19
  136. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000026.html +0 -51
  137. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000027.html +0 -19
  138. data/doc/rdoc/classes/ESI/Tag/Try.html +0 -161
  139. data/doc/rdoc/classes/ESI/Tag/Try.src/M000023.html +0 -40
  140. data/doc/rdoc/classes/ESI/Tag/Try.src/M000024.html +0 -18
  141. data/doc/rdoc/classes/ESI/Tag.html +0 -137
  142. data/doc/rdoc/classes/ESI.html +0 -169
  143. data/doc/rdoc/classes/MultiDirHandler.html +0 -198
  144. data/doc/rdoc/classes/MultiDirHandler.src/M000001.html +0 -20
  145. data/doc/rdoc/classes/MultiDirHandler.src/M000002.html +0 -28
  146. data/doc/rdoc/classes/MultiDirHandler.src/M000003.html +0 -22
  147. data/doc/rdoc/classes/Net/An/HTTP.html +0 -137
  148. data/doc/rdoc/classes/Net/An/HTTP.src/M000087.html +0 -17
  149. data/doc/rdoc/classes/Net/An/IORequest.html +0 -139
  150. data/doc/rdoc/classes/Net/An/IORequest.src/M000088.html +0 -17
  151. data/doc/rdoc/classes/Net/An/IOResponse.html +0 -139
  152. data/doc/rdoc/classes/Net/An/IOResponse.src/M000085.html +0 -17
  153. data/doc/rdoc/classes/Net/An/IOSocket.html +0 -137
  154. data/doc/rdoc/classes/Net/An/IOSocket.src/M000086.html +0 -17
  155. data/doc/rdoc/classes/Net/An.html +0 -114
  156. data/doc/rdoc/classes/Net.html +0 -119
  157. data/doc/rdoc/created.rid +0 -1
  158. data/doc/rdoc/files/COPYING.html +0 -168
  159. data/doc/rdoc/files/LICENSE.html +0 -605
  160. data/doc/rdoc/files/README.html +0 -361
  161. data/doc/rdoc/files/lib/esi/cache_rb.html +0 -113
  162. data/doc/rdoc/files/lib/esi/config_rb.html +0 -108
  163. data/doc/rdoc/files/lib/esi/dispatcher_rb.html +0 -109
  164. data/doc/rdoc/files/lib/esi/handler_rb.html +0 -121
  165. data/doc/rdoc/files/lib/esi/invalidator_rb.html +0 -117
  166. data/doc/rdoc/files/lib/esi/logger_rb.html +0 -108
  167. data/doc/rdoc/files/lib/esi/router_rb.html +0 -101
  168. data/doc/rdoc/files/lib/esi/tag/attempt_rb.html +0 -101
  169. data/doc/rdoc/files/lib/esi/tag/base_rb.html +0 -108
  170. data/doc/rdoc/files/lib/esi/tag/except_rb.html +0 -101
  171. data/doc/rdoc/files/lib/esi/tag/include_rb.html +0 -109
  172. data/doc/rdoc/files/lib/esi/tag/invalidate_rb.html +0 -109
  173. data/doc/rdoc/files/lib/esi/tag/try_rb.html +0 -108
  174. data/doc/rdoc/files/lib/multi_dirhandler_rb.html +0 -109
  175. data/doc/rdoc/files/lib/net/ahttp_rb.html +0 -109
  176. data/doc/rdoc/fr_class_index.html +0 -55
  177. data/doc/rdoc/fr_file_index.html +0 -44
  178. data/doc/rdoc/fr_method_index.html +0 -114
  179. data/doc/rdoc/index.html +0 -24
  180. data/doc/rdoc/rdoc-style.css +0 -208
  181. data/ext/esi/parser.rb +0 -49
  182. data/ext/esi/ruby_esi.rl +0 -135
  183. data/lib/esi/handler.rb +0 -221
  184. data/lib/net/ahttp.rb +0 -36
@@ -0,0 +1,106 @@
1
+ require 'fastthread'
2
+ require 'thread'
3
+ require 'stringio'
4
+
5
+
6
+ module ESI
7
+ class Response
8
+ attr_reader :active_buffer
9
+ attr_accessor :output
10
+
11
+ def initialize( output )
12
+ @lock = Mutex.new
13
+ @count = 0
14
+ @back_buffer = []
15
+ @output = output
16
+ @last_out = -1
17
+ @threads = []
18
+ @active_buffer = reserve_buffer
19
+ end
20
+
21
+ def update_output(output)
22
+ @lock.synchronize do
23
+ @output = output
24
+ end
25
+ end
26
+
27
+ def close_active_buffer
28
+ @lock.synchronize do
29
+ if !@active_buffer.closed_write?
30
+ @active_buffer.close_write
31
+ end
32
+ end
33
+ end
34
+
35
+ def back_buffer_ready?
36
+ @lock.synchronize do
37
+ @back_buffer[@last_out+1..@count].size > 2
38
+ end
39
+ end
40
+
41
+ def open_active_buffer
42
+ @lock.synchronize do
43
+ if @active_buffer.closed_write?
44
+ begin
45
+ @lock.unlock
46
+ @active_buffer = reserve_buffer
47
+ ensure
48
+ @lock.lock
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ # return's new buffer
55
+ def reserve_buffer
56
+ @lock.synchronize do
57
+ buffer = @back_buffer[@count] = StringIO.new
58
+ @count += 1
59
+ buffer
60
+ end
61
+ end
62
+
63
+ def send
64
+ @lock.synchronize do
65
+ # roll up requests
66
+ until @last_out == @count
67
+ o = @back_buffer[@last_out+1]
68
+ if o.nil? or !o.closed_write?
69
+ #puts "#{self} buffering...#{@last_out} to #{@count} #{@back_buffer[@last_out+1..@count].map{|b| b ? b.closed_write? : 'nil' }.join(',')}"
70
+ break
71
+ end
72
+ o.rewind
73
+ buf = o.read
74
+ #puts "#{Thread.current} #{self} sending: #{@last_out+1} #{buf.inspect}"
75
+ @back_buffer[@last_out+1] = nil # clear it out, release memory
76
+ @output << buf
77
+ @last_out += 1
78
+ end
79
+ end
80
+ end
81
+
82
+ def wait_thread(thread)
83
+ @threads << thread
84
+ end
85
+
86
+ def flush
87
+ @threads.each{|t| t.join }
88
+ @active_buffer.close_write
89
+ # roll up requests
90
+ @last_out = 0 if @last_out == -1
91
+ tail_buffer = (@back_buffer[@last_out..@back_buffer.size]||[])
92
+ #puts "\nflushing:#{Thread.current} #{self} with #{tail_buffer.inspect}"
93
+ while !tail_buffer.empty?
94
+ o = tail_buffer.shift
95
+ unless o.nil?
96
+ o.rewind
97
+ buf = o.read
98
+ #puts "#{Thread.current} #{self} flush : #{buf.inspect}"
99
+ @output << buf
100
+ end
101
+ #puts "#{self} sending: #{@count-tail_buffer.size}"
102
+ end
103
+ end
104
+
105
+ end
106
+ end
data/lib/esi/router.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
3
+
1
4
  module ESI
2
5
 
3
6
  # ESI Server is a reverse proxy caching server. It will forward all requests to app servers
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
3
+
1
4
  module ESI
2
5
  module Tag
3
6
  class Attempt < Base
data/lib/esi/tag/base.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
1
3
  require 'esi/logger'
2
4
 
3
5
  module ESI
@@ -5,7 +7,7 @@ module ESI
5
7
  class Base
6
8
  Validate = ['try','attempt','except','include','invalidate']
7
9
  attr_reader :attributes, :children, :name, :closed, :cache
8
-
10
+
9
11
  include ESI::Log
10
12
  extend ESI::Log
11
13
 
@@ -1,3 +1,5 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
1
3
  module ESI
2
4
  module Tag
3
5
  class Except < Base
@@ -1,69 +1,73 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
1
3
  require 'uri'
2
4
  require 'net/http'
5
+ require 'esi/parser'
3
6
 
4
7
  module ESI
5
8
  module Tag
6
-
7
- #
8
- #
9
- # ir = IncludeRequest.new( {'header1'=>'value1'} )
10
- #
11
- # ir.request( '/fragment' ) do|status,response|
12
- # if status
13
- # response.read_body do|str|
14
- # end
15
- # else
16
- # # error case
17
- # end
18
- # end
19
- #
20
- class IncludeRequest
21
- class Error
22
- attr_reader :message, :response
23
- def initialize(msg,response)
24
- @message = msg
25
- @response = response
9
+ class Include < Base
10
+ #
11
+ #
12
+ # ir = Request.new( {'header1'=>'value1'} )
13
+ #
14
+ # ir.request( '/fragment' ) do|status,response|
15
+ # if status
16
+ # response.read_body do|str|
17
+ # end
18
+ # else
19
+ # # error case
20
+ # end
21
+ # end
22
+ #
23
+ class Request
24
+ class Error
25
+ attr_reader :message, :response
26
+ def initialize(msg,response)
27
+ @message = msg
28
+ @response = response
29
+ end
26
30
  end
27
- end
28
- attr_reader :exception, :overflow_index # TODO
31
+ attr_reader :exception, :overflow_index # TODO
29
32
 
30
- def initialize(forward_headers)
31
- @headers = forward_headers
32
- end
33
+ def initialize(forward_headers)
34
+ @headers = forward_headers
35
+ end
33
36
 
34
- def request(uri, timeout = 1, alt_failover=nil, follow_limit=3)
35
- uri = URI.parse(uri) if uri.is_a?(String)
36
- http = Net::HTTP.new(uri.host, uri.port)
37
- http.read_timeout = timeout
38
- http.get2( uri.to_s, @headers ) do|response|
39
- case response
40
- when Net::HTTPSuccess
41
- yield true, response, uri
42
- when Net::HTTPRedirection
43
- ir = IncludeRequest.new(@headers)
44
- ir.request(URI.parse(response['location']), timeout, alt_failover, follow_limit - 1) do|s,r|
45
- yield s, r, URI.parse(response['location'])
46
- end
47
- else
48
- if alt_failover
49
- ir = IncludeRequest.new(@headers)
50
- ir.request(alt_failover, timeout, nil, follow_limit) do|s,r|
51
- yield s, r, URI.parse(alt_failover)
37
+ def request(uri, timeout = 1, alt_failover=nil, follow_limit=3)
38
+ uri = URI.parse(uri) if uri.is_a?(String)
39
+ Net::HTTP.start(uri.host, uri.port) do|http|
40
+ http.read_timeout = timeout if timeout and timeout > 0
41
+ rp = uri.query ? "#{uri.path}?#{uri.query}" : uri.path
42
+ http.request_get( rp, @headers ) do|response|
43
+ case response
44
+ when Net::HTTPSuccess
45
+ yield true, response, uri
46
+ when Net::HTTPRedirection
47
+ ir = Request.new(@headers)
48
+ ir.request(URI.parse(response['location']), timeout, alt_failover, follow_limit - 1) do|s,r|
49
+ yield s, r, URI.parse(response['location'])
50
+ end
51
+ else
52
+ if alt_failover
53
+ ir = Request.new(@headers)
54
+ ir.request(alt_failover, timeout, nil, follow_limit) do|s,r|
55
+ yield s, r, URI.parse(alt_failover)
56
+ end
57
+ else
58
+ yield false, Error.new("Failed to request fragment: #{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}", response), uri
59
+ end
52
60
  end
53
- else
54
- yield false, Error.new("Failed to request fragment: #{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}", response), uri
55
61
  end
56
62
  end
63
+ rescue Timeout::Error => e
64
+ yield false, Error.new("Failed to request fragment: #{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}, timeout error: #{e.message}", nil), uri
57
65
  end
58
- rescue Timeout::Error => e
59
- yield false, Error.new("Failed to request fragment: #{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}, timeout error: #{e.message}", nil), uri
60
- end
61
66
 
62
- end
63
-
64
- class Include < Base
67
+ end
65
68
 
66
69
  attr_accessor :depth, :max_depth
70
+
67
71
  def initialize(uri,headers,http_params,name,attrs,cache)
68
72
  super
69
73
  @depth = 0
@@ -76,114 +80,109 @@ module ESI
76
80
 
77
81
  def close( output, options = {} )
78
82
  super(output)
83
+ @output = output
79
84
 
80
- raise_on_error = options[:raise] || false
81
- ir = IncludeRequest.new(@http_params)
85
+ raise_on_error = options[:raise] || false # default to false
82
86
 
83
87
  src = @router.url_for(prepare_url_vars(@attributes["src"]))
84
88
  alt = @attributes['alt']
85
89
  alt = @router.url_for(prepare_url_vars(alt)) if alt
86
90
 
87
- parser = nil
91
+ prepare_parser
92
+
93
+ if @cache.cached?( src, @http_params )
94
+ send_from_cache( src )
95
+ else
96
+ send_from_surrogate( src, alt, raise_on_error )
97
+ end
98
+
99
+ end
88
100
 
101
+ protected
102
+ def prepare_parser
89
103
  if parse_fragment?
90
- parser = ESI::CParser.new
91
- parser.output = output
92
- parser.depth = (@depth+1)
93
-
94
- # NOTE: really bad things happen if we attempt to copy the closure from the main parser
95
- # in esi/handler.rb
96
-
97
- # handle start tags
98
- parser.start_tag_handler do|tag_name, attrs|
99
- tag = ESI::Tag::Base.create( @router,
100
- @headers,
101
- @http_params,
102
- tag_name.gsub(/esi:/,''),
103
- attrs,
104
- @cache )
105
- # set the tag depth
106
- tag.depth = (@depth+1) if tag.respond_to?(:depth=)
107
- tag.max_depth = @max_depth if tag.respond_to?(:max_depth=)
108
-
109
- if parser.esi_tag
110
- parser.esi_tag.add_child(tag)
111
- else
112
- parser.esi_tag = tag
104
+ @parser = ESI::Parser.new( @output, @router, @cache, @max_depth )
105
+ @parser.prepare( @headers, @http_params ) do|chars|
106
+ if @parser.response.active_buffer.closed_write?
107
+ @parser.response.open_active_buffer
108
+ @parser.response.send
113
109
  end
110
+ @parser.response.active_buffer << chars
114
111
  end
115
-
116
- # handle end tags
117
- parser.end_tag_handler do|tag_name|
118
- if parser.esi_tag.name == tag_name.gsub(/esi:/,'')
119
- parser.esi_tag.close(parser.output)
120
- parser.esi_tag = nil
121
- else
122
- parser.esi_tag.close_child(parser.output,tag_name)
123
- end
124
- end
125
-
112
+ @parser.depth = (@depth+1) # increment the depth
126
113
  end
114
+ end
127
115
 
116
+ def send_from_cache( src )
117
+ cached_fragment = @cache.get( src, @headers ).body
118
+ log_request "C"
119
+ if parse_fragment?
128
120
 
129
- if @cache.cached?( src, @http_params )
130
- cached_fragment = @cache.get( src, @headers ).body
131
- log_request "C"
132
- if parse_fragment?
133
-
134
- parser.process cached_fragment
135
- parser.finish
121
+ @parser.process cached_fragment
122
+ @parser.finish
136
123
 
137
- else
138
- output << cached_fragment
139
- end
140
-
141
124
  else
125
+ @output << cached_fragment
126
+ end
142
127
 
143
- ir.request(src, @attributes['timeout'].to_i, alt ) do|status,response,uri|
144
- if status
145
- # NOTE: it's important that we cache the unprocessed markup, because we need to
146
- # reprocess the esi:include vars even for cached content, this way we can have cached content
147
- # with HTTP_COOKIE vars and avoid re-requesting content
148
- log_request "R"
149
- cache_buffer = ""
150
- response.read_body do|s|
151
- cache_buffer << s
152
- if parse_fragment?
153
- parser.process s
154
- else
155
- output << s
156
- end
157
- end
158
-
159
- parser.finish if parse_fragment?
128
+ end
160
129
 
161
- if src != uri # these won't be equal if the fragment followed a redirect or used the alt condition
162
- if uri.query
163
- request_uri = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}?#{uri.query}"
164
- else
165
- request_uri = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
166
- end
130
+ def send_from_surrogate( src, alt, raise_on_error )
131
+ ir = Request.new(@http_params)
132
+ #timer = Time.now
133
+ ir.request(src, @attributes['timeout'].to_i, alt ) do|status,response,uri|
134
+ if status
135
+ # NOTE: it's important that we cache the unprocessed markup, because we need to
136
+ # reprocess the esi:include vars even for cached content, this way we can have cached content
137
+ # with HTTP_COOKIE vars and avoid re-requesting content
138
+ cache_buffer = ""
139
+ response.read_body do|s|
140
+ cache_buffer << s
141
+ if parse_fragment?
142
+ @parser.process s
167
143
  else
168
- request_uri = src
144
+ @output << s
169
145
  end
146
+ end
170
147
 
171
- @cache.put(request_uri, @http_params, 600, cache_buffer )
148
+ if parse_fragment?
149
+ @parser.finish
150
+ end
172
151
 
152
+ if src != uri # these won't be equal if the fragment followed a redirect or used the alt condition
153
+ if uri.query
154
+ request_uri = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}?#{uri.query}"
155
+ else
156
+ request_uri = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
157
+ end
173
158
  else
174
- # error/ check if the include has an onerror specifier
175
- return if @attributes['onerror'] == 'continue'
176
- # response is an IncludeRequest::Error
177
- raise response.message if raise_on_error
178
- # stop processing and return the error object
179
- return response
159
+ request_uri = src
180
160
  end
161
+
162
+ cache_ttl = (@attributes['max-age']||600) # defaults to 600... maybe should have this be configurable?
163
+ if cache_ttl.respond_to?(:match) and cache_ttl.match(/\+/)
164
+ total=0
165
+ cache_ttl.split('+').each {|comp| total+=comp.to_i}
166
+ cache_ttl = total
167
+ else
168
+ cache_ttl = cache_ttl.to_i
169
+ end
170
+
171
+ @cache.put(request_uri, @http_params, cache_ttl, cache_buffer )
172
+ #log_request "R #{src} #{Time.now - timer}\n"
173
+
174
+ else
175
+ # error/ check if the include has an onerror specifier
176
+ return if @attributes['onerror'] == 'continue'
177
+ # response is a Request::Error
178
+ raise response.message if raise_on_error
179
+ # stop processing and return the error object
180
+ return response
181
181
  end
182
182
  end
183
+ end
183
184
 
184
- parser = nil
185
185
 
186
- end
187
186
  end
188
187
 
189
188
  end