mongrel_esi 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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