rack-esi 0.1.1 → 0.1.2
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.
- data/README.markdown +3 -2
- data/VERSION +1 -1
- data/lib/rack-esi.rb +55 -33
- metadata +2 -2
data/README.markdown
CHANGED
@@ -11,7 +11,7 @@ for include, remove and comment.
|
|
11
11
|
* include limits (:includes => 32)
|
12
12
|
* support for <include> alt and noerror attributes
|
13
13
|
|
14
|
-
_It's for development purpose
|
14
|
+
_It's for development purpose..._
|
15
15
|
|
16
16
|
## Installation
|
17
17
|
|
@@ -20,7 +20,8 @@ _It's for development purpose since its still 0.1.x..._
|
|
20
20
|
## Rails Setup (environment.rb)
|
21
21
|
|
22
22
|
config.gem 'rack-esi'
|
23
|
-
|
23
|
+
require 'rack-esi'
|
24
|
+
config.middleware.insert_before config.middleware.first, Rack::ESI
|
24
25
|
|
25
26
|
## TODO
|
26
27
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/rack-esi.rb
CHANGED
@@ -3,7 +3,17 @@ require 'nokogiri'
|
|
3
3
|
|
4
4
|
class Rack::ESI
|
5
5
|
NS = { 'esi' => 'http://www.edge-delivery.org/esi/1.0' }
|
6
|
-
|
6
|
+
METHODS = { 'include' => :esi_include, 'remove' => nil, 'comment' => nil }
|
7
|
+
CSS = METHODS.keys.map { |cmd| "esi|#{ cmd }" } * ','
|
8
|
+
|
9
|
+
class Error < RuntimeError
|
10
|
+
def initialize(status, headers, response)
|
11
|
+
@status, @headers, @response = status, headers, response
|
12
|
+
end
|
13
|
+
def finish
|
14
|
+
return [@status, @headers, backtrace]
|
15
|
+
end
|
16
|
+
end
|
7
17
|
|
8
18
|
def initialize(app, options = {})
|
9
19
|
@app = app
|
@@ -17,49 +27,35 @@ class Rack::ESI
|
|
17
27
|
def call env, counter = { :recursion => 0, :includes => 0 }
|
18
28
|
return @app.call(env) if skip_path? env['PATH_INFO']
|
19
29
|
|
20
|
-
status, headers,
|
21
|
-
return status, headers,
|
30
|
+
status, headers, input = @app.call env.dup
|
31
|
+
return status, headers, input if skip_type? headers['Content-Type']
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
33
|
+
output = []
|
34
|
+
input.each { |body| output << compile_body(body, env, counter) }
|
35
|
+
|
36
|
+
Rack::Response.new(output, status, headers).finish
|
26
37
|
end
|
27
38
|
|
28
39
|
private
|
29
40
|
|
41
|
+
def with_compiled_path(env, path)
|
42
|
+
# TODO: should compile variables.
|
43
|
+
env.merge 'PATH_INFO' => path, 'REQUEST_URI' => path
|
44
|
+
end
|
45
|
+
|
30
46
|
def fetch(path, env, counter)
|
31
|
-
call env
|
47
|
+
call with_compiled_path(env, path), counter if path
|
48
|
+
rescue => e
|
49
|
+
return [500, {}, e.backtrace]
|
32
50
|
end
|
33
51
|
|
34
52
|
# Should I use XML::SAX::Parser?
|
35
|
-
def
|
53
|
+
def compile_body(body, env, counter)
|
36
54
|
document = Nokogiri.XML body
|
37
55
|
|
38
|
-
document.css(
|
39
|
-
|
40
|
-
|
41
|
-
next unless counter[:includes] < @max_includes
|
42
|
-
counter[:includes] += 1
|
43
|
-
begin
|
44
|
-
next unless counter[:recursion] < @max_recursion
|
45
|
-
counter[:recursion] += 1
|
46
|
-
status, headers, compiled = fetch node['src'], env, counter
|
47
|
-
status, headers, compiled = fetch node['alt'], env, counter if status != 200
|
48
|
-
ensure
|
49
|
-
counter[:recursion] -= 1
|
50
|
-
end
|
51
|
-
|
52
|
-
if status != 200
|
53
|
-
raise Error if node['onerror'] != 'continue'
|
54
|
-
compiled = []
|
55
|
-
end
|
56
|
-
|
57
|
-
data = '' and compiled.each { |body| data << body }
|
58
|
-
node.swap data
|
59
|
-
|
60
|
-
when 'remove', 'comment'
|
61
|
-
node.unlink
|
62
|
-
end
|
56
|
+
document.css(CSS, NS).each do |node|
|
57
|
+
method = METHODS[node.name] and send method, node, env, counter
|
58
|
+
node.unlink
|
63
59
|
end
|
64
60
|
|
65
61
|
document.to_xhtml
|
@@ -72,4 +68,30 @@ class Rack::ESI
|
|
72
68
|
@types !~ type
|
73
69
|
end
|
74
70
|
|
71
|
+
def max?(counter)
|
72
|
+
not counter[:includes] < @max_includes &&
|
73
|
+
counter[:recursion] < @max_recursion
|
74
|
+
end
|
75
|
+
|
76
|
+
def esi_include(node, env, counter)
|
77
|
+
return if max? counter
|
78
|
+
|
79
|
+
counter[:includes] += 1
|
80
|
+
counter[:recursion] += 1
|
81
|
+
|
82
|
+
status, headers, response = fetch node['src'], env, counter
|
83
|
+
status, headers, response = fetch node['alt'], env, counter if status != 200
|
84
|
+
|
85
|
+
if status == 200
|
86
|
+
data = ''
|
87
|
+
response.each { |inc| data << inc }
|
88
|
+
node.before data
|
89
|
+
elsif node['onerror'] != 'continue'
|
90
|
+
raise Error.new(status, headers, response)
|
91
|
+
end
|
92
|
+
|
93
|
+
ensure
|
94
|
+
counter[:recursion] -= 1
|
95
|
+
end
|
96
|
+
|
75
97
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-esi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Florian A\xC3\x9Fmann"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-27 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|