joshbuddy-esi-for-rack 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -14,18 +14,28 @@ class EsiForRack
14
14
  @lookup = lookup
15
15
  end
16
16
 
17
+ def self.response_body_to_str(response_body)
18
+ if response_body.respond_to? :to_str
19
+ response_body.to_str
20
+ elsif response_body.respond_to?(:each)
21
+ body = ''
22
+ response_body.each { |part|
23
+ body << part.to_s
24
+ }
25
+ body
26
+ else
27
+ raise TypeError, "stringable or iterable required"
28
+ end
29
+ end
30
+
17
31
  def call(env)
18
- @lookup ||= Lookup::PassThrough.new(@app, env)
19
-
32
+ @lookup ||= [Lookup::PassThrough.new(@app, env), Lookup::Http.new(@app, env)]
20
33
  request = Rack::Request.new(env)
21
34
  result = @app.call(env)
22
35
  response = Rack::Response.new(result[2], result[0], result[1])
23
36
 
24
37
  if response['Content-Type'] =~ /text\/html/
25
- body = ""
26
- response.body.each do |part|
27
- body << part
28
- end
38
+ body = EsiForRack.response_body_to_str(result.last)
29
39
 
30
40
  user_agent_hash = {}
31
41
  begin
@@ -48,10 +58,8 @@ class EsiForRack
48
58
  # error parsing ua
49
59
  end
50
60
 
51
-
52
-
53
61
  binding = {
54
- :HTTP_ACCEPT_LANGUAGE => Set.new((env['HTTP_ACCEPT_LANGUAGE'] || '').split(',').map{|l| l.strip.gsub(/q=[0-9]\.[0-9]{1,3}/, '').gsub(';','')}),
62
+ :HTTP_ACCEPT_LANGUAGE => Set.new((env['HTTP_ACCEPT_LANGUAGE'] || '').split(',').map{|l| l.gsub(/q=[0-9]\.[0-9]{1,3}/, '').gsub(';','').strip}),
55
63
  :HTTP_COOKIE => request.cookies,
56
64
  :HTTP_HOST => request.host,
57
65
  :HTTP_REFERER => request.referer,
@@ -59,25 +67,15 @@ class EsiForRack
59
67
  :QUERY_STRING => request.GET
60
68
  }
61
69
  context = Node::Context.new(binding, @lookup)
62
- [response.status, response.headers, [context.parse(body).to_s]]
70
+
71
+ parsed_body = context.parse(body).to_s
72
+ response.header['Content-Length'] = parsed_body.size.to_s
73
+
74
+ [response.status, response.headers, [parsed_body]]
63
75
  else
64
76
  result
65
77
  end
66
78
 
67
79
  end
68
80
 
69
- class IOWrapper
70
- def initialize(body)
71
- @body = body.each
72
- end
73
-
74
- def read
75
- @body.end?
76
- end
77
-
78
- def close
79
- #no-op
80
- end
81
- end
82
-
83
81
  end
@@ -1,8 +1,11 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
1
4
  class EsiForRack
2
5
 
3
6
  class Lookup
4
7
 
5
- class PassThrough < Lookup
8
+ class Http
6
9
 
7
10
  def initialize(app, env)
8
11
  @app = app
@@ -10,6 +13,26 @@ class EsiForRack
10
13
  end
11
14
 
12
15
  def [](path)
16
+ return unless path[0,4] == 'http'
17
+ uri = URI(path)
18
+ res = Net::HTTP.start(uri.host, uri.port) {|http|
19
+ http.get(uri.request_uri)
20
+ }
21
+ res.body if res.code == '200'
22
+ end
23
+
24
+ end
25
+
26
+ class PassThrough
27
+
28
+ def initialize(app, env)
29
+ @app = app
30
+ @env = env
31
+ end
32
+
33
+ def [](path)
34
+ return if path[0,4] == 'http'
35
+
13
36
  uri = URI(path)
14
37
 
15
38
  request = {
@@ -24,18 +47,7 @@ class EsiForRack
24
47
 
25
48
  response = @app.call(request)
26
49
  if response.first == 200
27
- response_body = response.last
28
- if response_body.respond_to? :to_str
29
- response_body.to_str
30
- elsif response_body.respond_to?(:each)
31
- body = ''
32
- response_body.each { |part|
33
- body << part.to_s
34
- }
35
- body
36
- else
37
- raise TypeError, "stringable or iterable required"
38
- end
50
+ EsiForRack.response_body_to_str(response.last)
39
51
  else
40
52
  nil
41
53
  end
@@ -19,21 +19,28 @@ class EsiForRack
19
19
 
20
20
  class Include < Node
21
21
 
22
- def execute
23
- @resolved_src = EsiAttributeLanguage::SimpleGrammar.parse(@node['src']).execute(context.resolver)
24
- @resolved_alt = EsiAttributeLanguage::SimpleGrammar.parse(@node['alt']).execute(context.resolver) if @node['alt']
25
- @continue_on_error = node['onerror'] == 'continue'
22
+ def resolved_src
23
+ EsiAttributeLanguage::SimpleGrammar.parse(@node['src']).execute(context.resolver)
24
+ end
25
+
26
+ def resolved_alt
27
+ EsiAttributeLanguage::SimpleGrammar.parse(@node['alt']).execute(context.resolver) if @node['alt']
28
+ end
26
29
 
27
- context.lookup[@resolved_src] ||
28
- (@resolved_alt && context.lookup[@resolved_alt]) ||
29
- (!@continue_on_error && raise(IncludeFailedError.new)) || nil
30
+ def continue_on_error?
31
+ node['onerror'] == 'continue'
32
+ end
33
+
34
+ def execute
35
+ context.lookup(resolved_src) or
36
+ (resolved_alt && context.lookup(resolved_alt)) or
37
+ (!continue_on_error? && raise(IncludeFailedError.new)) or nil
30
38
  end
31
39
 
32
40
  end
33
41
 
34
42
  class Vars < Node
35
- def execute
36
- #@content = node.inner_html
43
+ def execute
37
44
  @content = Rack::Utils.unescape(node.inner_html)
38
45
  EsiAttributeLanguage::SimpleGrammar.parse(@content).execute(context.resolver)
39
46
  end
@@ -84,12 +91,11 @@ class EsiForRack
84
91
 
85
92
  class Context
86
93
 
87
- attr_reader :resolver, :lookup, :doc
94
+ attr_reader :resolver, :doc
88
95
 
89
96
  def initialize(resolver, lookup)
90
97
  @resolver = resolver
91
- @lookup = lookup
92
-
98
+ @lookup = lookup.is_a?(Array) ? lookup : [lookup]
93
99
  @include = Include.new
94
100
  @choose = Choose.new
95
101
  @vars = Vars.new
@@ -97,6 +103,14 @@ class EsiForRack
97
103
 
98
104
  end
99
105
 
106
+ def lookup(url)
107
+ @lookup.each do |l|
108
+ resolved_body = l[url]
109
+ return resolved_body if resolved_body
110
+ end
111
+ nil
112
+ end
113
+
100
114
  def parse(document)
101
115
  document.gsub!('esi:', 'esi_')
102
116
 
@@ -113,19 +127,27 @@ class EsiForRack
113
127
 
114
128
  def process(doc_fragment)
115
129
  # have to go one at a time because of limitation of .css, its not a live list.
116
- while esi_node = doc_fragment.css('esi_try,esi_choose,esi_vars,esi_include')[0]
117
- case esi_node.name.to_sym
118
- when :esi_include
119
- @include.init(esi_node, self).execute_in_place!
120
- when :esi_choose
121
- @choose.init(esi_node, self).execute_in_place!
122
- when :esi_vars
123
- @vars.init(esi_node, self).execute_in_place!
124
- when :esi_try
125
- @try.init(esi_node, self).execute_in_place!
130
+ # ps, i'll only break if i totally have to
131
+ loop do
132
+ should_break = true
133
+ doc_fragment.css('esi_try,esi_choose,esi_vars,esi_include').each do |esi_node|
134
+ should_break = false
135
+ case esi_node.name.to_sym
136
+ when :esi_include
137
+ @include.init(esi_node, self).execute_in_place!
138
+ when :esi_choose
139
+ @choose.init(esi_node, self).execute_in_place!
140
+ when :esi_vars
141
+ @vars.init(esi_node, self).execute_in_place!
142
+ when :esi_try
143
+ @try.init(esi_node, self).execute_in_place!
144
+ break
145
+ end
126
146
  end
147
+ break if should_break
127
148
  end
128
149
  end
150
+
129
151
  end
130
152
 
131
153
  end
@@ -16,7 +16,7 @@ describe "esi cookie variable lookups" do
16
16
 
17
17
  request = Rack::MockRequest.env_for("/?#{Rack::Utils.build_query(vars)}")
18
18
  request['HTTP_COOKIE'] = 'id=1'
19
- builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>resource</body></html>\n"]
19
+ builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\nresource\n</body></html>\n"]
20
20
 
21
21
  end
22
22
 
@@ -15,7 +15,7 @@ describe "esi query string variable lookups" do
15
15
  end
16
16
 
17
17
  request = Rack::MockRequest.env_for("/?#{Rack::Utils.build_query(vars)}")
18
- builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>resource</body></html>\n"]
18
+ builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\nresource\n</body></html>\n"]
19
19
 
20
20
  end
21
21
 
@@ -2,7 +2,7 @@ require 'spec/spec_helper'
2
2
 
3
3
  describe "esi user agent variable lookups" do
4
4
 
5
- it "should lookup a cookie variable" do
5
+ it "should lookup a user agent variable" do
6
6
 
7
7
  vars = {'type' => 'user'}
8
8
  builder = Rack::Builder.new do
@@ -16,7 +16,7 @@ describe "esi user agent variable lookups" do
16
16
 
17
17
  request = Rack::MockRequest.env_for("/?#{Rack::Utils.build_query(vars)}")
18
18
  request['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2'
19
- builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\nbrowserosversion\n</body></html>\n"]
19
+ builder.call(request).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n browserosversion\n</body></html>\n"]
20
20
 
21
21
  end
22
22
 
@@ -1,5 +1,3 @@
1
- I_KNOW_I_AM_USING_AN_OLD_AND_BUGGY_VERSION_OF_LIBXML2 = true
2
-
3
1
  require 'rack'
4
2
  require 'lib/esi_for_rack'
5
3
 
@@ -3,11 +3,11 @@ require 'spec/spec_helper'
3
3
  describe "esi include" do
4
4
 
5
5
  it "should include a src" do
6
- build_app('spec/tags/fixtures/include/src.html', {'/great' => "<p>This is great</p>"}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><p>This is great</p></body></html>\n"]
6
+ build_app('spec/tags/fixtures/include/src.html', {'/great' => "<p>This is great</p>"}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>This is great</p>\n</body></html>\n"]
7
7
  end
8
8
 
9
9
  it "should include an alt if src is unavilable" do
10
- build_app('spec/tags/fixtures/include/alt.html', {'/alternate' => "<p>This is great</p>"}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><p>This is great</p></body></html>\n"]
10
+ build_app('spec/tags/fixtures/include/alt.html', {'/alternate' => "<p>This is great</p>"}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>This is great</p>\n</body></html>\n"]
11
11
  end
12
12
 
13
13
  it "should raise an error if src is unavilable" do
@@ -19,7 +19,7 @@ describe "esi include" do
19
19
  end
20
20
 
21
21
  it "should continue though, if onerror=continue" do
22
- build_app('spec/tags/fixtures/include/src_continue.html', {}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body></body></html>\n"]
22
+ build_app('spec/tags/fixtures/include/src_continue.html', {}).last.should == ["<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n\n</body></html>\n"]
23
23
  end
24
24
 
25
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joshbuddy-esi-for-rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hull
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-21 00:00:00 -07:00
12
+ date: 2009-07-27 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -87,6 +87,7 @@ files:
87
87
  - spec/tags/vars_spec.rb
88
88
  has_rdoc: false
89
89
  homepage: http://github.com/joshbuddy/esi_for_rack
90
+ licenses:
90
91
  post_install_message:
91
92
  rdoc_options:
92
93
  - --charset=UTF-8
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  requirements: []
108
109
 
109
110
  rubyforge_project:
110
- rubygems_version: 1.2.0
111
+ rubygems_version: 1.3.5
111
112
  signing_key:
112
113
  specification_version: 3
113
114
  summary: ESI for Rack