mongrel_esi 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +14 -6
- data/doc/rdoc/classes/ESI/CParser.html +122 -0
- data/doc/rdoc/classes/ESI/Cache.html +178 -0
- data/doc/rdoc/classes/ESI/Cache.src/M000085.html +17 -0
- data/doc/rdoc/classes/ESI/Cache.src/M000086.html +20 -0
- data/doc/rdoc/classes/ESI/Config.html +333 -0
- data/doc/rdoc/classes/ESI/Config.src/M000052.html +18 -0
- data/doc/rdoc/classes/ESI/Config.src/M000053.html +18 -0
- data/doc/rdoc/classes/ESI/Config.src/M000054.html +35 -0
- data/doc/rdoc/classes/ESI/Config.src/M000055.html +38 -0
- data/doc/rdoc/classes/ESI/Config.src/M000056.html +23 -0
- data/doc/rdoc/classes/ESI/Config.src/M000057.html +18 -0
- data/doc/rdoc/classes/ESI/Config.src/M000058.html +20 -0
- data/doc/rdoc/classes/ESI/Config.src/M000059.html +18 -0
- data/doc/rdoc/classes/ESI/Config.src/M000060.html +24 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.html +212 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000064.html +19 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000065.html +19 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000066.html +18 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000067.html +18 -0
- data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000068.html +18 -0
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.html +187 -0
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000061.html +19 -0
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000062.html +21 -0
- data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000063.html +21 -0
- data/doc/rdoc/classes/ESI/Dispatcher.html +172 -0
- data/doc/rdoc/classes/ESI/Dispatcher.src/M000087.html +22 -0
- data/doc/rdoc/classes/ESI/Dispatcher.src/M000088.html +18 -0
- data/doc/rdoc/classes/ESI/Fragment.html +218 -0
- data/doc/rdoc/classes/ESI/Fragment.src/M000100.html +20 -0
- data/doc/rdoc/classes/ESI/Fragment.src/M000101.html +18 -0
- data/doc/rdoc/classes/ESI/Fragment.src/M000102.html +18 -0
- data/doc/rdoc/classes/ESI/Invalidator.html +131 -0
- data/doc/rdoc/classes/ESI/Invalidator.src/M000004.html +41 -0
- data/doc/rdoc/classes/ESI/Log.html +221 -0
- data/doc/rdoc/classes/ESI/Log.src/M000030.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000031.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000032.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000033.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000034.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000035.html +18 -0
- data/doc/rdoc/classes/ESI/Log.src/M000036.html +18 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.html +314 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000040.html +24 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000041.html +22 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000042.html +19 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000043.html +23 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000044.html +18 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000045.html +19 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000046.html +18 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000047.html +18 -0
- data/doc/rdoc/classes/ESI/MemcachedCache.src/M000048.html +17 -0
- data/doc/rdoc/classes/ESI/Parser.html +184 -0
- data/doc/rdoc/classes/ESI/Parser.src/M000049.html +51 -0
- data/doc/rdoc/classes/ESI/Parser.src/M000050.html +39 -0
- data/doc/rdoc/classes/ESI/Parser.src/M000051.html +19 -0
- data/doc/rdoc/classes/ESI/Processor.html +194 -0
- data/doc/rdoc/classes/ESI/Processor.src/M000037.html +26 -0
- data/doc/rdoc/classes/ESI/Processor.src/M000038.html +44 -0
- data/doc/rdoc/classes/ESI/Processor.src/M000039.html +26 -0
- data/doc/rdoc/classes/ESI/Proxy.html +304 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000069.html +20 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000070.html +55 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000071.html +53 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000072.html +25 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000073.html +19 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000074.html +27 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000075.html +18 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000076.html +28 -0
- data/doc/rdoc/classes/ESI/Proxy.src/M000077.html +29 -0
- data/doc/rdoc/classes/ESI/Response.html +250 -0
- data/doc/rdoc/classes/ESI/Response.src/M000078.html +23 -0
- data/doc/rdoc/classes/ESI/Response.src/M000079.html +18 -0
- data/doc/rdoc/classes/ESI/Response.src/M000080.html +21 -0
- data/doc/rdoc/classes/ESI/Response.src/M000081.html +20 -0
- data/doc/rdoc/classes/ESI/Response.src/M000082.html +25 -0
- data/doc/rdoc/classes/ESI/Response.src/M000083.html +18 -0
- data/doc/rdoc/classes/ESI/Response.src/M000084.html +33 -0
- data/doc/rdoc/classes/ESI/Router.html +212 -0
- data/doc/rdoc/classes/ESI/Router.src/M000098.html +36 -0
- data/doc/rdoc/classes/ESI/Router.src/M000099.html +25 -0
- data/doc/rdoc/classes/ESI/RubyCache.html +278 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000089.html +20 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000090.html +20 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000091.html +20 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000092.html +22 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000093.html +18 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000094.html +22 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000095.html +18 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000096.html +18 -0
- data/doc/rdoc/classes/ESI/RubyCache.src/M000097.html +18 -0
- data/doc/rdoc/classes/ESI/Tag.html +141 -0
- data/doc/rdoc/classes/ESI/Tag/Attempt.html +113 -0
- data/doc/rdoc/classes/ESI/Tag/Base.html +237 -0
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000026.html +23 -0
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000027.html +22 -0
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000028.html +22 -0
- data/doc/rdoc/classes/ESI/Tag/Base.src/M000029.html +17 -0
- data/doc/rdoc/classes/ESI/Tag/Container.html +206 -0
- data/doc/rdoc/classes/ESI/Tag/Container.src/M000015.html +20 -0
- data/doc/rdoc/classes/ESI/Tag/Container.src/M000016.html +22 -0
- data/doc/rdoc/classes/ESI/Tag/Container.src/M000017.html +25 -0
- data/doc/rdoc/classes/ESI/Tag/Except.html +184 -0
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000018.html +21 -0
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000019.html +20 -0
- data/doc/rdoc/classes/ESI/Tag/Except.src/M000020.html +18 -0
- data/doc/rdoc/classes/ESI/Tag/Include.html +257 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000005.html +20 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000006.html +18 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000007.html +34 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000008.html +22 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000009.html +27 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000010.html +30 -0
- data/doc/rdoc/classes/ESI/Tag/Include.src/M000011.html +51 -0
- data/doc/rdoc/classes/ESI/Tag/Include/Request.html +199 -0
- data/doc/rdoc/classes/ESI/Tag/Include/Request.src/M000012.html +18 -0
- data/doc/rdoc/classes/ESI/Tag/Include/Request.src/M000013.html +44 -0
- data/doc/rdoc/classes/ESI/Tag/Include/Request/Error.html +155 -0
- data/doc/rdoc/classes/ESI/Tag/Include/Request/Error.src/M000014.html +19 -0
- data/doc/rdoc/classes/ESI/Tag/Invalidate.html +171 -0
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000023.html +19 -0
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000024.html +51 -0
- data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000025.html +19 -0
- data/doc/rdoc/classes/ESI/Tag/Try.html +154 -0
- data/doc/rdoc/classes/ESI/Tag/Try.src/M000021.html +38 -0
- data/doc/rdoc/classes/ESI/Tag/Try.src/M000022.html +18 -0
- data/doc/rdoc/classes/MultiDirHandler.html +198 -0
- data/doc/rdoc/classes/MultiDirHandler.src/M000001.html +20 -0
- data/doc/rdoc/classes/MultiDirHandler.src/M000002.html +28 -0
- data/doc/rdoc/classes/MultiDirHandler.src/M000003.html +22 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/COPYING.html +167 -0
- data/doc/rdoc/files/LICENSE.html +605 -0
- data/doc/rdoc/files/README.html +359 -0
- data/doc/rdoc/files/ext/esi/common_rl.html +160 -0
- data/doc/rdoc/files/ext/esi/esi_parser_c.html +101 -0
- data/doc/rdoc/files/ext/esi/parser_c.html +101 -0
- data/doc/rdoc/files/ext/esi/parser_h.html +101 -0
- data/doc/rdoc/files/ext/esi/parser_rl.html +827 -0
- data/doc/rdoc/files/ext/esi/test/common_rl.html +160 -0
- data/doc/rdoc/files/ext/esi/test/parser_c.html +101 -0
- data/doc/rdoc/files/ext/esi/test/parser_h.html +101 -0
- data/doc/rdoc/files/ext/esi/test/parser_rl.html +827 -0
- data/doc/rdoc/files/ext/esi/test/sp_c.html +101 -0
- data/doc/rdoc/files/ext/esi/test/test_c.html +101 -0
- data/doc/rdoc/files/lib/esi/cache_rb.html +119 -0
- data/doc/rdoc/files/lib/esi/config_rb.html +114 -0
- data/doc/rdoc/files/lib/esi/dispatcher_rb.html +108 -0
- data/doc/rdoc/files/lib/esi/invalidator_rb.html +114 -0
- data/doc/rdoc/files/lib/esi/logger_rb.html +108 -0
- data/doc/rdoc/files/lib/esi/parser_rb.html +120 -0
- data/doc/rdoc/files/lib/esi/processor_rb.html +115 -0
- data/doc/rdoc/files/lib/esi/proxy_rb.html +123 -0
- data/doc/rdoc/files/lib/esi/response_rb.html +116 -0
- data/doc/rdoc/files/lib/esi/router_rb.html +107 -0
- data/doc/rdoc/files/lib/esi/tag/attempt_rb.html +114 -0
- data/doc/rdoc/files/lib/esi/tag/base_rb.html +114 -0
- data/doc/rdoc/files/lib/esi/tag/container_rb.html +115 -0
- data/doc/rdoc/files/lib/esi/tag/except_rb.html +114 -0
- data/doc/rdoc/files/lib/esi/tag/include_rb.html +116 -0
- data/doc/rdoc/files/lib/esi/tag/invalidate_rb.html +115 -0
- data/doc/rdoc/files/lib/esi/tag/try_rb.html +115 -0
- data/doc/rdoc/files/lib/esi/version_rb.html +101 -0
- data/doc/rdoc/files/lib/multi_dirhandler_rb.html +109 -0
- data/doc/rdoc/fr_class_index.html +53 -0
- data/doc/rdoc/fr_file_index.html +59 -0
- data/doc/rdoc/fr_method_index.html +128 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/ext/esi/esi_parser.c +12 -1
- data/ext/esi/parser.c +492 -3927
- data/ext/esi/parser.rl +83 -14
- data/ext/esi/test/parser.c +1587 -367
- data/ext/esi/test/parser.rl +83 -14
- data/ext/esi/test/sp.c +125 -0
- data/ext/esi/test/test.c +198 -6
- data/lib/esi/cache.rb +5 -8
- data/lib/esi/config.rb +3 -3
- data/lib/esi/dispatcher.rb +2 -4
- data/lib/esi/parser.rb +26 -13
- data/lib/esi/processor.rb +13 -35
- data/lib/esi/proxy.rb +113 -44
- data/lib/esi/response.rb +23 -55
- data/lib/esi/router.rb +0 -11
- data/lib/esi/tag/attempt.rb +2 -1
- data/lib/esi/tag/base.rb +1 -24
- data/lib/esi/tag/container.rb +40 -0
- data/lib/esi/tag/except.rb +3 -1
- data/lib/esi/tag/include.rb +53 -62
- data/lib/esi/tag/try.rb +16 -18
- data/lib/esi/version.rb +9 -0
- data/test/integration/handler_test.rb +49 -12
- data/test/integration/help.rb +12 -0
- data/test/load_test.rb +8 -4
- data/test/load_test_ab.rb +8 -0
- data/test/sample.html +31 -0
- data/test/unit/help.rb +12 -8
- data/test/unit/include_request_test.rb +14 -21
- data/test/unit/parser_test.rb +2 -1
- data/test/unit/response_test.rb +4 -8
- data/tools/rakehelp.rb +1 -1
- metadata +216 -5
data/lib/esi/cache.rb
CHANGED
@@ -168,17 +168,14 @@ module ESI
|
|
168
168
|
|
169
169
|
def cached?( uri, params )
|
170
170
|
key = cache_key(uri,params)
|
171
|
-
@semaphore.synchronize
|
172
|
-
|
173
|
-
fragment and fragment.valid?
|
174
|
-
end
|
171
|
+
fragment = @semaphore.synchronize { @cache[key] }
|
172
|
+
fragment and fragment.valid?
|
175
173
|
end
|
176
174
|
|
177
175
|
def get( uri, params )
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
end
|
176
|
+
key = cache_key(uri,params)
|
177
|
+
fragment = @semaphore.synchronize { @cache[key] }
|
178
|
+
fragment.dup if fragment and fragment.respond_to?(:dup)
|
182
179
|
end
|
183
180
|
|
184
181
|
def put( uri, params, max_age, body )
|
data/lib/esi/config.rb
CHANGED
@@ -58,15 +58,15 @@ module ESI
|
|
58
58
|
use_esi = false
|
59
59
|
allowed_content_types = @config[:allowed_content_types]
|
60
60
|
|
61
|
-
if allowed_content_types and headers["
|
61
|
+
if allowed_content_types and headers["content-type"] and allowed_content_types.respond_to?(:detect)
|
62
62
|
use_esi = allowed_content_types.detect do |type|
|
63
|
-
headers["
|
63
|
+
headers["content-type"].match( type )
|
64
64
|
end
|
65
65
|
use_esi = true if use_esi
|
66
66
|
end
|
67
67
|
|
68
68
|
if @config[:enable_for_surrogate_only]
|
69
|
-
use_esi = headers["
|
69
|
+
use_esi = headers["surrogate-control"] and /ESI/.match(headers["surrogate-control"])
|
70
70
|
end
|
71
71
|
|
72
72
|
use_esi
|
data/lib/esi/dispatcher.rb
CHANGED
@@ -2,7 +2,7 @@ require 'esi/proxy'
|
|
2
2
|
|
3
3
|
module ESI
|
4
4
|
|
5
|
-
class Dispatcher <
|
5
|
+
class Dispatcher < Mongrel::HttpHandler
|
6
6
|
attr_reader :config, :router
|
7
7
|
|
8
8
|
Thread.abort_on_exception = false
|
@@ -10,15 +10,13 @@ module ESI
|
|
10
10
|
def initialize( options )
|
11
11
|
super()
|
12
12
|
@config = ESI::Config.new( options )
|
13
|
-
@router = nil
|
14
13
|
if @config.start_invalidator?
|
15
14
|
ESI::Invalidator.start( self )
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
18
|
def process(request, response)
|
20
|
-
@
|
21
|
-
super
|
19
|
+
ESI::Proxy.new(@config).process(request,response)
|
22
20
|
end
|
23
21
|
|
24
22
|
end
|
data/lib/esi/parser.rb
CHANGED
@@ -20,28 +20,38 @@ module ESI
|
|
20
20
|
@response = ESI::Response.new( output )
|
21
21
|
|
22
22
|
end_tag_handler do|tag_name|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
#puts "rb end #{tag_name.inspect}"
|
24
|
+
if self.esi_tag.name == tag_name.sub(/esi:/,'')
|
25
|
+
|
26
|
+
if tag_name.match(/try|include/) # run these in parallel
|
27
|
+
tag = self.esi_tag.clone
|
28
|
+
tag_buffer = @response.partial_buffer
|
29
|
+
|
30
|
+
#puts "start #{tag_name}"
|
31
|
+
thread = Thread.new(tag,tag_buffer) do|tag,buffer|
|
32
|
+
begin
|
33
|
+
tag.close(buffer)
|
34
|
+
ensure
|
35
|
+
buffer.close_write
|
36
|
+
#puts "finish #{tag_name}"
|
37
|
+
end
|
32
38
|
end
|
39
|
+
@response.wait_thread( thread )
|
40
|
+
else
|
41
|
+
self.esi_tag.close( @response.active_buffer )
|
33
42
|
end
|
43
|
+
|
34
44
|
self.esi_tag = nil
|
35
45
|
|
36
|
-
@response.wait_thread( thread )
|
37
46
|
else
|
38
47
|
self.esi_tag.close_child(self.output,tag_name)
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
43
|
-
def prepare( request_params, http_params
|
52
|
+
def prepare( request_params, http_params )
|
44
53
|
start_tag_handler do|tag_name, attrs|
|
54
|
+
#puts "rb start #{tag_name.inspect}"
|
45
55
|
tag = ESI::Tag::Base.create( @router,
|
46
56
|
request_params,
|
47
57
|
http_params,
|
@@ -52,13 +62,16 @@ module ESI
|
|
52
62
|
tag.depth = self.depth if tag.respond_to?(:depth=)
|
53
63
|
tag.max_depth = @max_depth if tag.respond_to?(:max_depth=)
|
54
64
|
|
55
|
-
if self.esi_tag
|
65
|
+
if self.esi_tag and self.esi_tag.respond_to?(:add_child)
|
56
66
|
self.esi_tag.add_child(tag)
|
57
67
|
else
|
58
68
|
self.esi_tag = tag
|
59
69
|
end
|
60
70
|
end
|
61
|
-
self.
|
71
|
+
self.output_handler do|chars|
|
72
|
+
@response.active_buffer << chars
|
73
|
+
@response.send
|
74
|
+
end
|
62
75
|
end
|
63
76
|
|
64
77
|
def finish
|
data/lib/esi/processor.rb
CHANGED
@@ -8,43 +8,29 @@ module ESI
|
|
8
8
|
|
9
9
|
include ESI::Log
|
10
10
|
|
11
|
-
def initialize( config, router )
|
11
|
+
def initialize( config, router, cache_buffer = nil )
|
12
12
|
@config = config
|
13
13
|
@router = router
|
14
14
|
@chunk_count = 0
|
15
15
|
@chunk_size = @config[:chunk_size] || 4096
|
16
|
+
@bytes_sent = 0
|
16
17
|
@max_depth = @config[:max_depth] || 3
|
17
18
|
@chunk_buffer = StringIO.new # when buffer reaches chunk_size write to the http_response socket
|
18
19
|
@parser = ESI::Parser.new( @chunk_buffer, @router, @config.cache, @max_depth )
|
20
|
+
@cache_buffer = cache_buffer
|
19
21
|
end
|
20
|
-
|
21
|
-
def send_head( http_response, status )
|
22
|
-
|
23
|
-
http_response.header["Transfer-Encoding"] = "chunked"
|
24
|
-
# this is the important part, rather then send the whole document back we send in chunks
|
25
|
-
# each fragment is roughly in it's own chunk, this does mean we require http 1.1, chunk size is still a limit
|
26
|
-
header = Mongrel::Const::STATUS_FORMAT % [status, Mongrel::HTTP_STATUS_CODES[status]]
|
27
|
-
header.gsub!(/Connection: close\r\n/,'')
|
28
|
-
http_response.header.out.rewind
|
29
|
-
header << http_response.header.out.read + Mongrel::Const::LINE_END
|
30
|
-
header.gsub!(/Status:.*?\r\n/,'')
|
31
|
-
http_response.write( header )
|
32
|
-
|
33
|
-
#print header
|
34
|
-
|
35
|
-
end
|
36
|
-
|
22
|
+
|
37
23
|
def send_body( http_request, params, http_response, proxy_response )
|
38
24
|
|
39
25
|
@http_response = http_response
|
40
26
|
|
41
27
|
# prepare the parser given the raw request params and the preprocessed request params
|
42
|
-
@parser.prepare( http_request.params, params )
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@
|
28
|
+
@parser.prepare( http_request.params, params )
|
29
|
+
|
30
|
+
# feed data to the parser
|
31
|
+
proxy_response.read_body do |data|
|
32
|
+
@parser.process data
|
33
|
+
@cache_buffer << data if @cache_buffer
|
48
34
|
if @chunk_buffer.size > @chunk_size
|
49
35
|
send_chunk
|
50
36
|
@chunk_buffer = StringIO.new
|
@@ -52,19 +38,11 @@ module ESI
|
|
52
38
|
end
|
53
39
|
end
|
54
40
|
|
55
|
-
#timer = Time.now
|
56
|
-
# feed data to the parser
|
57
|
-
proxy_response.read_body { |data| @parser.process data }
|
58
|
-
#puts "processing time: #{Time.now - timer}"
|
59
|
-
|
60
|
-
#timer = Time.now
|
61
|
-
# finish the request
|
62
41
|
@parser.finish
|
63
|
-
#puts "finish time: #{Time.now - timer}"
|
64
42
|
|
65
43
|
send_chunk
|
66
44
|
|
67
|
-
@chunk_count
|
45
|
+
[@chunk_count,@bytes_sent]
|
68
46
|
rescue => e
|
69
47
|
STDERR.puts "\n#{e.message}: #{e.backtrace.join("\n")}\n"
|
70
48
|
ensure
|
@@ -76,10 +54,10 @@ module ESI
|
|
76
54
|
@chunk_buffer.rewind
|
77
55
|
size = @chunk_buffer.size
|
78
56
|
chunk_header = "#{"%x" % size}" + Mongrel::Const::LINE_END
|
79
|
-
#
|
57
|
+
#print chunk_header
|
80
58
|
@http_response.write( chunk_header ) # write the chunk size
|
81
|
-
#puts buffer.inspect
|
82
59
|
@http_response.write( @chunk_buffer.read + Mongrel::Const::LINE_END ) # write the chunk
|
60
|
+
@bytes_sent += size
|
83
61
|
|
84
62
|
@chunk_count += 1
|
85
63
|
end
|
data/lib/esi/proxy.rb
CHANGED
@@ -9,63 +9,131 @@ require 'esi/cache'
|
|
9
9
|
require 'esi/config'
|
10
10
|
require 'esi/router'
|
11
11
|
require 'esi/processor'
|
12
|
+
require 'esi/version'
|
12
13
|
|
13
14
|
module ESI
|
14
15
|
|
15
|
-
class Proxy
|
16
|
-
attr_reader :config, :router
|
16
|
+
class Proxy
|
17
|
+
attr_reader :config, :router, :cache_buffer
|
17
18
|
include ESI::Log
|
19
|
+
SERVER="mongrel-esi/#{ESI::VERSION::STRING}"
|
20
|
+
|
21
|
+
def initialize( config )
|
22
|
+
@config = config
|
23
|
+
@router = config.router
|
24
|
+
@cache_buffer = nil
|
25
|
+
end
|
18
26
|
|
19
27
|
def process(request, response)
|
20
28
|
|
21
29
|
start = Time.now
|
22
30
|
status = 200
|
23
|
-
url = @router.url_for(request.params["REQUEST_URI"])
|
24
31
|
|
25
|
-
|
32
|
+
http_params = http_params(request.params)
|
26
33
|
|
27
|
-
|
34
|
+
url = @router.url_for(request.params["REQUEST_URI"])
|
35
|
+
#log_debug "#{request.params["REQUEST_METHOD"]} => #{url}"
|
28
36
|
chunk_count = 0
|
37
|
+
bytes_sent = 0
|
29
38
|
uri = URI.parse(url)
|
30
39
|
|
31
40
|
path_with_query = uri.query ? "#{uri.path}?#{uri.query}" : uri.path
|
41
|
+
|
42
|
+
if @config.cache.cached?( path_with_query, http_params )
|
43
|
+
cache_buffer = @config.cache.get( path_with_query, http_params ).body
|
44
|
+
bytes_sent = send_esi_buffered( status, response, request, http_params, cache_buffer )
|
45
|
+
else
|
46
|
+
proxy_request = (request.params["REQUEST_METHOD"] == "POST") ?
|
47
|
+
Net::HTTP::Post.new( path_with_query, http_params ) :
|
48
|
+
Net::HTTP::Get.new( path_with_query, http_params )
|
49
|
+
|
50
|
+
# open the conneciton up so we can start to stream the connection
|
51
|
+
Net::HTTP.start(uri.host, uri.port).request(proxy_request,request.body.read) do|proxy_response|
|
52
|
+
chunk_count,bytes_sent = send_response( request, response, http_params, proxy_response )
|
53
|
+
end # end request
|
54
|
+
|
55
|
+
if !@control.nil? and !@cache_buffer.nil? and @control['max-age'].to_i > 0 and @cache_buffer.size > 0
|
56
|
+
@cache_buffer.rewind
|
57
|
+
@config.cache.put(path_with_query, http_params, @control['max-age'].to_i, @cache_buffer.read )
|
58
|
+
end
|
32
59
|
|
33
|
-
|
34
|
-
Net::HTTP::Post.new( path_with_query, params ) :
|
35
|
-
Net::HTTP::Get.new( path_with_query, params )
|
36
|
-
|
37
|
-
proxy_connection = Net::HTTP.start(uri.host, uri.port)
|
60
|
+
end
|
38
61
|
|
39
|
-
|
40
|
-
|
62
|
+
rescue => e
|
63
|
+
STDERR.puts "\n#{e.message}: error at #{e.backtrace.first} msg at #{__FILE__}:#{__LINE__}\n"
|
64
|
+
ensure
|
65
|
+
log_request "\n#{url}, #{Time.now - start} seconds with status #{status} and #{chunk_count} chunks, #{bytes_sent} bytes\n"
|
66
|
+
end
|
41
67
|
|
42
|
-
|
68
|
+
protected
|
69
|
+
def send_response( http_request, http_response, http_params, proxy_response )
|
70
|
+
status = read_status( proxy_response )
|
71
|
+
|
72
|
+
headers = copy_headers( proxy_response )
|
73
|
+
|
74
|
+
if proxy_response.header["Surrogate-Control"]
|
75
|
+
@control = {}
|
76
|
+
proxy_response.header["Surrogate-Control"].split(',').each do |pair|
|
77
|
+
k,v = pair.strip.split('=')
|
78
|
+
@control[k] = v
|
79
|
+
end
|
80
|
+
if @control['max-age'].to_i > 0
|
81
|
+
@cache_buffer = StringIO.new
|
82
|
+
end
|
83
|
+
end
|
43
84
|
|
44
|
-
copy_headers( response.header, proxy_response ) unless status >= 500
|
45
85
|
|
46
|
-
|
47
|
-
|
86
|
+
if status >= 500 or !@config.enable_esi_processor?( proxy_response )
|
87
|
+
headers.each do|k,v|
|
88
|
+
http_response.header[k] = v
|
89
|
+
end
|
90
|
+
proxy_direct( http_response, status, proxy_response )
|
91
|
+
else
|
92
|
+
if http_request.params["HTTP_VERSION"].match(/1.0/)
|
93
|
+
buffer = proxy_response.read_body
|
94
|
+
bytes=send_esi_buffered( status, http_response, http_request, http_params, buffer )
|
95
|
+
@cache_buffer << buffer if @cache_buffer
|
96
|
+
[0,bytes]
|
97
|
+
else
|
98
|
+
header = Mongrel::Const::STATUS_FORMAT % [status, Mongrel::HTTP_STATUS_CODES[status]]
|
99
|
+
headers.each {|k,v| header << "#{k}: #{v}\r\n" }
|
100
|
+
header << "Transfer-Encoding: chunked\r\n\r\n"
|
101
|
+
http_response.write( header )
|
102
|
+
proxy_filter_esi( http_request, http_response, http_params, proxy_response )
|
103
|
+
end
|
104
|
+
end
|
48
105
|
|
49
|
-
|
50
|
-
proxy_response.read_body do|fragment|
|
51
|
-
out << fragment
|
52
|
-
end
|
106
|
+
end
|
53
107
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
108
|
+
def proxy_direct( http_response, status, proxy_response )
|
109
|
+
bytes_sent = 0
|
110
|
+
http_response.start(status, true) do|head,out|
|
111
|
+
proxy_response.read_body do|fragment|
|
112
|
+
out << fragment
|
113
|
+
bytes_sent += fragment.size
|
59
114
|
end
|
60
|
-
end
|
115
|
+
end
|
116
|
+
return [0,bytes_sent]
|
117
|
+
end
|
61
118
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
119
|
+
def proxy_filter_esi( http_request, http_response, http_params, proxy_response )
|
120
|
+
processor = Processor.new( @config, @router, @cache_buffer )
|
121
|
+
processor.send_body( http_request, http_params, http_response, proxy_response )
|
122
|
+
end
|
123
|
+
|
124
|
+
def send_esi_buffered( status, response, request, http_params, buffer )
|
125
|
+
bytes = 0
|
126
|
+
response.start(status, true) do|head,out|
|
127
|
+
head["Server"] = SERVER
|
128
|
+
parser = ESI::Parser.new( out, @router, @config.cache, 3 )
|
129
|
+
parser.prepare( request.params, http_params )
|
130
|
+
parser.process buffer
|
131
|
+
parser.finish
|
132
|
+
bytes = out.size
|
133
|
+
end
|
134
|
+
bytes
|
66
135
|
end
|
67
136
|
|
68
|
-
protected
|
69
137
|
|
70
138
|
def read_status(response)
|
71
139
|
Net::HTTPResponse::CODE_TO_OBJ.select { |k,v| v == response.class }.first[0].to_i rescue 500
|
@@ -74,29 +142,30 @@ module ESI
|
|
74
142
|
def http_params(params)
|
75
143
|
updated_params = {}
|
76
144
|
params.each do|k,v|
|
77
|
-
|
78
|
-
|
79
|
-
k[0,5]
|
80
|
-
|
145
|
+
if k.match(/HTTP/i)
|
146
|
+
k = k.split('_').collect { |t| t.capitalize }.join('-')
|
147
|
+
if k[0,5] =='Http-'
|
148
|
+
k[0,5] = ''
|
149
|
+
updated_params[k] = v
|
150
|
+
end
|
81
151
|
end
|
82
152
|
end
|
83
153
|
updated_params
|
84
154
|
end
|
85
155
|
|
86
|
-
def copy_headers(
|
156
|
+
def copy_headers(response)
|
157
|
+
headers = {}
|
87
158
|
response.to_hash.each do |k,v|
|
88
159
|
# for Set-Cookie we need to split on ,
|
89
160
|
# some edge cases with , since things like expires might be a date with , in them.
|
90
161
|
k = k.split(/-/).map{|s| s.capitalize }.join('-')
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
else
|
96
|
-
head[k] = v unless k == "Content-Length" or k == "Surrogate-Control" or k == "Server"
|
97
|
-
end
|
162
|
+
|
163
|
+
next if k.match(/Content-Length|Surrogate-Control|Server|Connection|Status/i)
|
164
|
+
|
165
|
+
headers[k] = v
|
98
166
|
end
|
99
|
-
|
167
|
+
headers["Server"] = SERVER
|
168
|
+
headers
|
100
169
|
end
|
101
170
|
|
102
171
|
end # Handler
|
data/lib/esi/response.rb
CHANGED
@@ -1,81 +1,49 @@
|
|
1
|
+
# Copyright (c) 2008 Todd A. Fisher
|
2
|
+
# see LICENSE
|
1
3
|
require 'fastthread'
|
2
4
|
require 'thread'
|
3
5
|
require 'stringio'
|
4
6
|
|
5
|
-
|
6
7
|
module ESI
|
7
8
|
class Response
|
8
9
|
attr_reader :active_buffer
|
9
10
|
attr_accessor :output
|
10
11
|
|
11
12
|
def initialize( output )
|
12
|
-
@lock = Mutex.new
|
13
13
|
@count = 0
|
14
14
|
@back_buffer = []
|
15
15
|
@output = output
|
16
|
-
@last_out =
|
16
|
+
@last_out = 0
|
17
17
|
@threads = []
|
18
|
-
@active_buffer = reserve_buffer
|
18
|
+
@active_buffer = reserve_buffer
|
19
19
|
end
|
20
20
|
|
21
21
|
def update_output(output)
|
22
|
-
@
|
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
|
22
|
+
@output = output
|
39
23
|
end
|
40
24
|
|
41
|
-
def
|
42
|
-
@
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@active_buffer = reserve_buffer
|
47
|
-
ensure
|
48
|
-
@lock.lock
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
25
|
+
def partial_buffer
|
26
|
+
@active_buffer.close_write
|
27
|
+
temp = reserve_buffer
|
28
|
+
@active_buffer = reserve_buffer
|
29
|
+
temp
|
52
30
|
end
|
53
31
|
|
54
32
|
# return's new buffer
|
55
33
|
def reserve_buffer
|
56
|
-
@
|
57
|
-
|
58
|
-
|
59
|
-
buffer
|
60
|
-
end
|
34
|
+
buffer = @back_buffer[@count] = StringIO.new
|
35
|
+
@count += 1
|
36
|
+
buffer
|
61
37
|
end
|
62
38
|
|
63
39
|
def send
|
64
|
-
@
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
40
|
+
check_buffers = @back_buffer[@last_out..@count]
|
41
|
+
|
42
|
+
for buffer in check_buffers do
|
43
|
+
break if buffer.nil? or !buffer.closed_write?
|
44
|
+
buffer.rewind
|
45
|
+
@output << buffer.read
|
46
|
+
@last_out += 1
|
79
47
|
end
|
80
48
|
end
|
81
49
|
|
@@ -85,17 +53,17 @@ module ESI
|
|
85
53
|
|
86
54
|
def flush
|
87
55
|
@threads.each{|t| t.join }
|
88
|
-
@active_buffer.close_write
|
56
|
+
@active_buffer.close_write if !@active_buffer.closed_write?
|
89
57
|
# roll up requests
|
90
58
|
@last_out = 0 if @last_out == -1
|
91
59
|
tail_buffer = (@back_buffer[@last_out..@back_buffer.size]||[])
|
92
|
-
#puts "\nflushing
|
60
|
+
#puts "\nflushing: #{tail_buffer.inspect} from #{@back_buffer.inspect}"
|
93
61
|
while !tail_buffer.empty?
|
94
62
|
o = tail_buffer.shift
|
95
63
|
unless o.nil?
|
96
64
|
o.rewind
|
97
65
|
buf = o.read
|
98
|
-
#puts "
|
66
|
+
#puts "flush : #{buf.inspect}"
|
99
67
|
@output << buf
|
100
68
|
end
|
101
69
|
#puts "#{self} sending: #{@count-tail_buffer.size}"
|