mikehale-rat-hole 0.1.7 → 0.1.8

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.
@@ -1,25 +1,31 @@
1
- === 0.1.7 / 2009-02-25
1
+ = 0.1.8
2
+
3
+ * bug fixes
4
+ * use jeweler instead of hoe
5
+ * add test harness
6
+
7
+ = 0.1.7
2
8
 
3
9
  * add support for tidy
4
10
  * update api to not require request/response to be returned
5
11
  * require rack 0.9.1 or greater
6
12
 
7
- === 0.1.6 / 2008-12-18
13
+ = 0.1.6
8
14
 
9
15
  * properly calculate request_uri if query_string is empty
10
16
 
11
- === 0.1.5 / 2008-12-18
17
+ = 0.1.5
12
18
 
13
19
  * calculate request_uri = path_info + query_string
14
20
 
15
- === 0.1.4 / 2008-12-18
21
+ = 0.1.4
16
22
 
17
23
  * update process_server_response hook to include rack_request
18
24
 
19
- === 0.1.2 / 2008-12-17
25
+ = 0.1.2
20
26
 
21
27
  * use patched-hoe from newgem
22
28
 
23
- === 0.1.0 / 2008-12-17
29
+ = 0.1.0
24
30
 
25
31
  * First release.
data/Manifest.txt CHANGED
@@ -1,9 +1,11 @@
1
- History.txt
1
+ CHANGELOG.rdoc
2
2
  Manifest.txt
3
3
  README.rdoc
4
4
  Rakefile
5
5
  lib/rat_hole.rb
6
+ lib/rat_hole_test.rb
6
7
  lib/util.rb
7
8
  rat-hole.gemspec
8
9
  test/mock_request.rb
9
10
  test/test_rat_hole.rb
11
+ VERSION.yml
data/README.rdoc CHANGED
@@ -46,6 +46,20 @@ You can also modify the response from the server to cleanup html tweak headers e
46
46
 
47
47
  Rack::Handler::Mongrel.run(app, {:Host => 'localhost', :Port => 5001})
48
48
 
49
+ === Testing your RatHole into existance
50
+ class PoliticalAgendaRatHoleTest < RatHoleTest
51
+ def test_has_proper_response
52
+ through_the(PoliticalAgendaRatHole, 'terralien.com') do |raw_response, app_response|
53
+ assert_equal raw_response.status.to_i, app_response.status.to_i
54
+ assert !raw_response.headers.has_key?('Ron-Paul')
55
+ assert app_response.headers.has_key?('Ron-Paul')
56
+
57
+ assert !raw_response.body.to_s.include?('http://ronpaul.com')
58
+ assert app_response.body.to_s.include?('http://ronpaul.com')
59
+ end
60
+ end
61
+ end
62
+
49
63
  == INSTALL:
50
64
  * sudo gem install mikehale-rat-hole
51
65
 
@@ -60,8 +74,10 @@ You can also modify the response from the server to cleanup html tweak headers e
60
74
  * handle server down
61
75
  * handle gziped content (accept-encoding, transfer-encoding)
62
76
  * maybe use a pool of Net::HTTP connections to speed things up
63
- * provide an easy way for testing rat holes
64
- * write up some rathole's for common tasks
77
+ * write up some rathole's for common tasks (logging)
78
+ * move to rspec?
79
+ * support post, head, delete, etc?
80
+ * add caching? can apache do this for us?
65
81
 
66
82
  == Credits
67
83
  * Michael Hale (http://halethegeek.com)
@@ -70,7 +86,7 @@ You can also modify the response from the server to cleanup html tweak headers e
70
86
  == LICENSE
71
87
  The MIT License
72
88
 
73
- Copyright (c) 2008 Michael Hale & David Bogus
89
+ Copyright (c) 2008-2009 Michael Hale & David Bogus
74
90
 
75
91
  Permission is hereby granted, free of charge, to any person obtaining a copy
76
92
  of this software and associated documentation files (the "Software"), to deal
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 8
data/lib/rat_hole.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'net/http'
2
- require 'rubygems'
3
2
  require 'rack'
4
3
  require 'delegate'
5
4
  require 'util'
@@ -7,8 +6,6 @@ require 'open3'
7
6
 
8
7
  class RatHole
9
8
 
10
- VERSION = '0.1.7'
11
-
12
9
  def initialize(host, tidy=false)
13
10
  @host = host
14
11
  @tidy = tidy
@@ -25,7 +22,6 @@ class RatHole
25
22
  def call(env)
26
23
  Net::HTTP.start(@host) do |http|
27
24
  http.instance_eval{@socket = MethodSpy.new(@socket){|method| method =~ /#{ENV['RH_METHOD_SPY_FILTER']}/}} if $DEBUG
28
-
29
25
  env.delete('HTTP_ACCEPT_ENCODING')
30
26
  source_request = Rack::Request.new(env)
31
27
  process_user_request(source_request)
@@ -41,9 +37,6 @@ class RatHole
41
37
  response = http.get(request_uri, source_headers)
42
38
  elsif source_request.post?
43
39
  post = Net::HTTP::Post.new(request_uri, source_headers)
44
- class << post
45
- include HTTPHeaderPatch
46
- end
47
40
  post.form_data = source_request.POST
48
41
  response = http.request(post)
49
42
  end
@@ -52,17 +45,23 @@ class RatHole
52
45
  headers = response.to_hash
53
46
  body = response.body || ''
54
47
  body = tidy_html(body) if @tidy
55
- headers.delete('transfer-encoding')
48
+ headers.delete('Transfer-Encoding')
56
49
 
57
50
  server_response = Rack::Response.new(body, code, headers)
51
+ whack_array(server_response)
58
52
  process_server_response(server_response, source_request)
59
- if server_response.headers.has_key?("content-length")
60
- server_response.headers["content-length"] = server_response.headers["content-length"].first
61
- end
62
53
  server_response.finish
63
54
  end
64
55
  end
65
56
 
57
+ def whack_array(server_response)
58
+ server_response.headers.each do |k, v|
59
+ if v.is_a?(Array) && v.size == 1
60
+ server_response[k] = v.first
61
+ end
62
+ end
63
+ end
64
+
66
65
  def tidy_html(body)
67
66
  if `which tidy` == ''
68
67
  $stderr.puts "tidy not found in path"
@@ -87,4 +86,4 @@ end
87
86
  # This class simply extends RatHole and does nothing.
88
87
  # It's only useful for making sure that you have everything hooked up correctly.
89
88
  class EmptyRatHole < RatHole
90
- end
89
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+
3
+ class RatHoleTest < Test::Unit::TestCase
4
+ def through_the(rathole_klass, host, uri='/', headers={})
5
+ app = Rack::Builder.new do
6
+ use Rack::ShowExceptions
7
+ use Rack::ShowStatus
8
+ run rathole_klass.new(host)
9
+ end
10
+
11
+ app_response = Rack::MockRequest.new(app).get(uri, headers)
12
+ raw_response = Net::HTTP.start(host) do |http|
13
+ http.get(uri, headers)
14
+ end
15
+ # Wrap raw_response in Rack::Response to make things easier to work with.
16
+ raw_headers = raw_response.to_hash
17
+ raw_response = Rack::Response.new(raw_response.body, raw_response.code, raw_headers)
18
+ normalize_headers(raw_response.headers)
19
+ normalize_headers(app_response.headers)
20
+ yield(raw_response, app_response)
21
+ end
22
+
23
+ def normalize_headers(headers)
24
+ new_headers = headers.inject({}){|h,e|
25
+ k,v = e
26
+ # the value of these headers changes
27
+ v = nil if k =~ /cookie|date|runtime|last-modified/i
28
+ # skip headers that rat-hole removes
29
+ unless k =~ /transfer/i
30
+ v = v.first if v.is_a?(Array) && v.size == 1 #normalize things
31
+ h.merge!(k => v)
32
+ end
33
+ h
34
+ }
35
+ headers.replace(new_headers)
36
+ end
37
+
38
+ def test_nothing #make autotest happy
39
+ end
40
+ end
data/lib/util.rb CHANGED
@@ -32,7 +32,18 @@ class String
32
32
  end
33
33
  end
34
34
 
35
- module HTTPHeaderPatch
35
+ module Net::HTTPHeader
36
+ def to_hash
37
+ new_headers = @header.dup
38
+ @header.each do |k,v|
39
+ new_headers.delete(k)
40
+ new_headers[k.to_camel_case] = v
41
+ end
42
+ new_headers
43
+ end
44
+ end
45
+
46
+ class Net::HTTP::Post
36
47
  # handle multiple parameters with the same name
37
48
  def form_data=(params, sep = '&')
38
49
  self.body = params.map {|key,value|
@@ -1,11 +1,10 @@
1
1
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
2
 
3
- require 'rubygems'
4
3
  require 'rr'
5
4
  require 'delegate'
6
5
  require 'test/unit'
7
- require 'ruby-debug'
8
6
  require 'rat_hole'
7
+ require 'rat_hole_test'
9
8
  require 'mock_request'
10
9
  require 'hpricot'
11
10
 
@@ -121,6 +120,16 @@ class TestRatHole < Test::Unit::TestCase
121
120
  assert_equal(expected_headers, proxied_request.headers)
122
121
  end
123
122
 
123
+ def test_content_type
124
+ mock_server(:headers=>{'content-type' => ['image/gif']})
125
+ response = send_get_request
126
+ assert_equal 'image/gif', response.headers['Content-Type']
127
+
128
+ mock_server
129
+ response = send_get_request
130
+ assert_equal 'text/html', response.headers['Content-Type']
131
+ end
132
+
124
133
  def test_convert_rack_env_to_http_headers_more_data
125
134
  expected_headers = {
126
135
  "X-Forwarded-Host"=>"www.example.com",
@@ -173,63 +182,35 @@ class TestRatHole < Test::Unit::TestCase
173
182
  send_post_request('', '/uri?with=param')
174
183
  assert_equal('/uri?with=param', proxied_request.uri)
175
184
  end
185
+ end
176
186
 
177
- def test_systemic_empty_rathole
178
- host = 'halethegeek.com'
179
- app = EmptyRatHole.new(host)
180
- app_response = Rack::MockRequest.new(app).get('/', {})
181
- raw_response = Net::HTTP.start(host) do |http|
182
- http.get('/', {})
187
+ class TestEmptyRatHole < RatHoleTest
188
+ def test_has_proper_response
189
+ through_the(EmptyRatHole, 'halethegeek.com') do |raw_response, app_response|
190
+ assert_not_equal 0, raw_response.headers
191
+ assert_equal raw_response.status.to_i, app_response.status.to_i
192
+ assert_equal raw_response.headers, app_response.headers
193
+ assert_equal raw_response.body.to_s, app_response.body.to_s
183
194
  end
184
- # Wrap raw_response in Rack::Response to make things easier to work with.
185
- raw_response = Rack::Response.new(raw_response.body, raw_response.code, raw_response.to_hash)
186
-
187
- assert_equal raw_response.status.to_i, app_response.status.to_i
188
- assert_equal normalize_headers(raw_response.headers), normalize_headers(app_response.headers)
189
- assert_equal raw_response.body.to_s, app_response.body.to_s
190
195
  end
196
+ end
191
197
 
192
- def test_systemic_political_agenda
193
- host = 'terralien.com'
194
- app = Rack::Builder.new do
195
- use Rack::ShowExceptions
196
- use Rack::ShowStatus
197
- run PoliticalAgendaRatHole.new(host)
198
- end
199
-
200
- app_response = Rack::MockRequest.new(app).get('/', {})
201
- raw_response = Net::HTTP.start(host) do |http|
202
- http.get('/', {})
198
+ class PoliticalAgendaRatHoleTest < RatHoleTest
199
+ def test_has_proper_response
200
+ through_the(PoliticalAgendaRatHole, 'terralien.com') do |raw_response, app_response|
201
+ assert_equal raw_response.status.to_i, app_response.status.to_i
202
+ assert !raw_response.headers.has_key?('Ron-Paul')
203
+ assert app_response.headers.has_key?('Ron-Paul')
204
+
205
+ assert !raw_response.body.to_s.include?('http://ronpaul.com')
206
+ assert app_response.body.to_s.include?('http://ronpaul.com')
203
207
  end
204
- # Wrap raw_response in Rack::Response to make things easier to work with.
205
- raw_response = Rack::Response.new(raw_response.body, raw_response.code, raw_response.to_hash)
206
- raw_headers = normalize_headers(raw_response.headers)
207
- app_headers = normalize_headers(app_response.headers)
208
-
209
- assert_equal raw_response.status.to_i, app_response.status.to_i
210
- assert !raw_headers.has_key?('Ron-Paul')
211
- assert app_headers.has_key?('Ron-Paul')
212
-
213
- assert !raw_response.body.to_s.include?('http://ronpaul.com')
214
- assert app_response.body.to_s.include?('http://ronpaul.com')
215
- end
216
-
217
- def normalize_headers(headers)
218
- headers.inject({}){|h,e|
219
- k,v = e
220
- # don't compare headers that change or that we remove
221
- unless k =~ /cookie|transfer|date|runtime/i
222
- v = [v] unless v.is_a? Array #normalize things
223
- h.merge!(k => v)
224
- end
225
- h
226
- }
227
208
  end
228
209
  end
229
210
 
230
211
  class PoliticalAgendaRatHole < RatHole
231
212
  def process_server_response(rack_response, rack_request)
232
- if(rack_response.content_type == 'text/html')
213
+ if(rack_response.content_type =~ /text\/html/)
233
214
  doc = Hpricot(rack_response.body.first)
234
215
  (doc/"a").set('href', 'http://ronpaul.com')
235
216
  rack_response.body.first.replace(doc.to_html)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mikehale-rat-hole
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Hale
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-25 00:00:00 -08:00
13
+ date: 2009-02-26 00:00:00 -08:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -23,82 +23,30 @@ dependencies:
23
23
  - !ruby/object:Gem::Version
24
24
  version: 0.9.1
25
25
  version:
26
- - !ruby/object:Gem::Dependency
27
- name: rr
28
- type: :development
29
- version_requirement:
30
- version_requirements: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 0.6.0
35
- version:
36
- - !ruby/object:Gem::Dependency
37
- name: hpricot
38
- type: :development
39
- version_requirement:
40
- version_requirements: !ruby/object:Gem::Requirement
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- version: 0.6.164
45
- version:
46
- - !ruby/object:Gem::Dependency
47
- name: newgem
48
- type: :development
49
- version_requirement:
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 1.1.0
55
- version:
56
- - !ruby/object:Gem::Dependency
57
- name: cucumber
58
- type: :development
59
- version_requirement:
60
- version_requirements: !ruby/object:Gem::Requirement
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- version: 0.1.12
65
- version:
66
- - !ruby/object:Gem::Dependency
67
- name: hoe
68
- type: :development
69
- version_requirement:
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- version: 1.8.0
75
- version:
76
- description: Rat Hole is a handy library for creating a rack compliant http proxy that allows you to modify the request from the user and the response from the server. The name is inspired by why's mousehole[http://code.whytheluckystiff.net/mouseHole/]
26
+ description: Rat Hole is a handy library for creating a rack compliant http proxy that allows you to modify the request from the user and the response from the server.
77
27
  email: mikehale@gmail.com
78
28
  executables: []
79
29
 
80
30
  extensions: []
81
31
 
82
- extra_rdoc_files:
83
- - History.txt
84
- - Manifest.txt
85
- - README.rdoc
32
+ extra_rdoc_files: []
33
+
86
34
  files:
87
- - History.txt
35
+ - CHANGELOG.rdoc
88
36
  - Manifest.txt
89
37
  - README.rdoc
90
- - Rakefile
38
+ - VERSION.yml
91
39
  - lib/rat_hole.rb
40
+ - lib/rat_hole_test.rb
92
41
  - lib/util.rb
93
- - rat-hole.gemspec
94
42
  - test/mock_request.rb
95
43
  - test/test_rat_hole.rb
96
44
  has_rdoc: true
97
45
  homepage: http://github.com/mikehale/rat-hole
98
46
  post_install_message:
99
47
  rdoc_options:
100
- - --main
101
- - README.rdoc
48
+ - --inline-source
49
+ - --charset=UTF-8
102
50
  require_paths:
103
51
  - lib
104
52
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -115,10 +63,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
63
  version:
116
64
  requirements: []
117
65
 
118
- rubyforge_project: rat-hole
66
+ rubyforge_project:
119
67
  rubygems_version: 1.2.0
120
68
  signing_key:
121
69
  specification_version: 2
122
- summary: Rack compliant proxy
123
- test_files:
124
- - test/test_rat_hole.rb
70
+ summary: Rack compliant http proxy
71
+ test_files: []
72
+
data/Rakefile DELETED
@@ -1,30 +0,0 @@
1
- $LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
2
- require 'rubygems'
3
- require 'hoe-patched' # because it supports README.*
4
- require 'rat_hole'
5
-
6
- Hoe.new('rat-hole', RatHole::VERSION) do |p|
7
- p.summary = 'Rack compliant proxy'
8
- p.description = p.paragraphs_of('README.rdoc', 0...1).to_s
9
- p.url = 'http://github.com/mikehale/rat-hole'
10
- p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
11
- p.extra_deps << ['rack', '>= 0.9.1']
12
- p.extra_dev_deps << ['rr', '>= 0.6.0']
13
- p.extra_dev_deps << ['hpricot', '>= 0.6.164']
14
- p.extra_dev_deps << ['newgem', '>= 1.1.0']
15
- p.extra_dev_deps << ['cucumber', '>= 0.1.12']
16
- p.author << 'Michael Hale'
17
- p.author << 'David Bogus'
18
- p.email = 'mikehale@gmail.com'
19
- end
20
-
21
- desc %(Update the gemspec so that github will build a new gem: http://gems.github.com/)
22
- task :update_gemspec do
23
- begin
24
- old_stdout = STDOUT.dup
25
- STDOUT.reopen('rat-hole.gemspec')
26
- Rake::Task["debug_gem"].invoke
27
- ensure
28
- STDOUT.reopen(old_stdout)
29
- end
30
- end
data/rat-hole.gemspec DELETED
@@ -1,50 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- Gem::Specification.new do |s|
4
- s.name = %q{rat-hole}
5
- s.version = "0.1.7"
6
-
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Michael Hale", "David Bogus"]
9
- s.date = %q{2009-02-25}
10
- s.description = %q{Rat Hole is a handy library for creating a rack compliant http proxy that allows you to modify the request from the user and the response from the server. The name is inspired by why's mousehole[http://code.whytheluckystiff.net/mouseHole/]}
11
- s.email = %q{mikehale@gmail.com}
12
- s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.rdoc"]
13
- s.files = ["History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "lib/rat_hole.rb", "lib/util.rb", "rat-hole.gemspec", "test/mock_request.rb", "test/test_rat_hole.rb"]
14
- s.has_rdoc = true
15
- s.homepage = %q{http://github.com/mikehale/rat-hole}
16
- s.rdoc_options = ["--main", "README.rdoc"]
17
- s.require_paths = ["lib"]
18
- s.rubyforge_project = %q{rat-hole}
19
- s.rubygems_version = %q{1.3.1}
20
- s.summary = %q{Rack compliant proxy}
21
- s.test_files = ["test/test_rat_hole.rb"]
22
-
23
- if s.respond_to? :specification_version then
24
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
- s.specification_version = 2
26
-
27
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
- s.add_runtime_dependency(%q<rack>, [">= 0.9.1"])
29
- s.add_development_dependency(%q<rr>, [">= 0.6.0"])
30
- s.add_development_dependency(%q<hpricot>, [">= 0.6.164"])
31
- s.add_development_dependency(%q<newgem>, [">= 1.1.0"])
32
- s.add_development_dependency(%q<cucumber>, [">= 0.1.12"])
33
- s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
34
- else
35
- s.add_dependency(%q<rack>, [">= 0.9.1"])
36
- s.add_dependency(%q<rr>, [">= 0.6.0"])
37
- s.add_dependency(%q<hpricot>, [">= 0.6.164"])
38
- s.add_dependency(%q<newgem>, [">= 1.1.0"])
39
- s.add_dependency(%q<cucumber>, [">= 0.1.12"])
40
- s.add_dependency(%q<hoe>, [">= 1.8.0"])
41
- end
42
- else
43
- s.add_dependency(%q<rack>, [">= 0.9.1"])
44
- s.add_dependency(%q<rr>, [">= 0.6.0"])
45
- s.add_dependency(%q<hpricot>, [">= 0.6.164"])
46
- s.add_dependency(%q<newgem>, [">= 1.1.0"])
47
- s.add_dependency(%q<cucumber>, [">= 0.1.12"])
48
- s.add_dependency(%q<hoe>, [">= 1.8.0"])
49
- end
50
- end