rack-esi 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.markdown +3 -2
  2. data/VERSION +1 -1
  3. data/lib/rack-esi.rb +55 -33
  4. 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 since its still 0.1.x..._
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
- config.middleware.use(Rack::ESI, opts = {})
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
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
- Error = Class.new RuntimeError
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, source = @app.call env
21
- return status, headers, source if skip_type? headers['Content-Type']
30
+ status, headers, input = @app.call env.dup
31
+ return status, headers, input if skip_type? headers['Content-Type']
22
32
 
23
- Rack::Response.new { |target|
24
- source.each { |body| target.write compile(body, env, counter) }
25
- }.finish
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.merge('PATH_INFO' => path), counter if path
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 compile(body, env, counter)
53
+ def compile_body(body, env, counter)
36
54
  document = Nokogiri.XML body
37
55
 
38
- document.css('esi|include,esi|remove,esi|comment', NS).each do |node|
39
- case node.name
40
- when 'include'
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.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-26 00:00:00 +01:00
12
+ date: 2009-11-27 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency