rack-proxy 0.0.1

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.
@@ -0,0 +1 @@
1
+ pkg
@@ -0,0 +1,28 @@
1
+ require "rake/testtask"
2
+
3
+ task :test do
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+ end
10
+
11
+ task :default => :test
12
+
13
+ begin
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "rack-proxy"
17
+ gem.summary = "A request/response rewriting HTTP proxy. A Rack app."
18
+ gem.description = "A Rack app that provides request/response rewriting proxy capabilities with streaming."
19
+ gem.email = "jacek.becela@gmail.com"
20
+ gem.homepage = "http://github.com/ncr/rack-proxy"
21
+ gem.authors = ["Jacek Becela"]
22
+ gem.add_dependency "rack"
23
+ gem.add_development_dependency "rack-test"
24
+ end
25
+ Jeweler::GemcutterTasks.new
26
+ rescue LoadError
27
+ puts "Jeweler not available. Install it with: gem install jeweler"
28
+ end
data/Readme ADDED
@@ -0,0 +1 @@
1
+ A request/response rewriting HTTP proxy. A Rack app.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,88 @@
1
+ # We are hacking net/http to change semantics of streaming handling
2
+ # from "block" semantics to regular "return" semnatics.
3
+ # We need it to construct a streamable rack triplet:
4
+ #
5
+ # [status, headers, streamable_body]
6
+ #
7
+ # See http://github.com/aniero/rack-streaming-proxy
8
+ # for alternative that uses additional process.
9
+ #
10
+ # BTW I don't like monkey patching either
11
+ # but this is not real monkey patching.
12
+ # I just added some methods and named them very uniquely
13
+ # to avoid eventual conflicts. You're safe. Trust me.
14
+
15
+ require 'net/http'
16
+
17
+ class Net::HTTP
18
+ # Original #request with block semantics.
19
+ #
20
+ # def request(req, body = nil, &block)
21
+ # unless started?
22
+ # start {
23
+ # req['connection'] ||= 'close'
24
+ # return request(req, body, &block)
25
+ # }
26
+ # end
27
+ # if proxy_user()
28
+ # unless use_ssl?
29
+ # req.proxy_basic_auth proxy_user(), proxy_pass()
30
+ # end
31
+ # end
32
+ #
33
+ # req.set_body_internal body
34
+ # begin_transport req
35
+ # req.exec @socket, @curr_http_version, edit_path(req.path)
36
+ # begin
37
+ # res = HTTPResponse.read_new(@socket)
38
+ # end while res.kind_of?(HTTPContinue)
39
+ # res.reading_body(@socket, req.response_body_permitted?) {
40
+ # yield res if block_given?
41
+ # }
42
+ # end_transport req, res
43
+ #
44
+ # res
45
+ # end
46
+
47
+ def begin_request_hacked(req)
48
+ begin_transport req
49
+ req.exec @socket, @curr_http_version, edit_path(req.path)
50
+ begin
51
+ res = Net::HTTPResponse.read_new(@socket)
52
+ end while res.kind_of?(Net::HTTPContinue)
53
+ res.begin_reading_body_hacked(@socket, req.response_body_permitted?)
54
+ @req_hacked, @res_hacked = req, res
55
+ @res_hacked
56
+ end
57
+
58
+ def end_request_hacked
59
+ @res_hacked.end_reading_body_hacked
60
+ end_transport @req_hacked, @res_hacked
61
+ @res_hacked
62
+ end
63
+ end
64
+
65
+ class Net::HTTPResponse
66
+ # Original #reading_body with block semantics
67
+ #
68
+ # def reading_body(sock, reqmethodallowbody) #:nodoc: internal use only
69
+ # @socket = sock
70
+ # @body_exist = reqmethodallowbody && self.class.body_permitted?
71
+ # begin
72
+ # yield
73
+ # self.body # ensure to read body
74
+ # ensure
75
+ # @socket = nil
76
+ # end
77
+ # end
78
+
79
+ def begin_reading_body_hacked(sock, reqmethodallowbody)
80
+ @socket = sock
81
+ @body_exist = reqmethodallowbody && self.class.body_permitted?
82
+ end
83
+
84
+ def end_reading_body_hacked
85
+ self.body
86
+ @socket = nil
87
+ end
88
+ end
@@ -0,0 +1,49 @@
1
+ require "net_http_hacked"
2
+
3
+ module Rack
4
+
5
+ # Wraps the hacked net/http in a Rack way.
6
+ class HttpStreamingResponse
7
+ def initialize(request, host, port = nil)
8
+ @request, @host, @port = request, host, port
9
+ end
10
+
11
+ def status
12
+ response.code
13
+ end
14
+
15
+ def headers
16
+ h = Utils::HeaderHash.new
17
+
18
+ response.each_header do |k, v|
19
+ h[k] = v
20
+ end
21
+
22
+ h
23
+ end
24
+
25
+ def body
26
+ self
27
+ end
28
+
29
+ def each(&block)
30
+ response.read_body(&block)
31
+ ensure
32
+ session.end_request_hacked
33
+ end
34
+
35
+ protected
36
+
37
+ # Net::HTTPResponse
38
+ def response
39
+ @response ||= session.begin_request_hacked(@request)
40
+ end
41
+
42
+ # Net::HTTP
43
+ def session
44
+ @session ||= Net::HTTP.start(@host, @port)
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,54 @@
1
+ require "net_http_hacked"
2
+ require "rack/http_streaming_response"
3
+
4
+ module Rack
5
+
6
+ # Subclass and bring your own #rewrite_request and #rewrite_response
7
+ class Proxy
8
+ def call(env)
9
+ rewrite_response(perform_request(rewrite_request(Rack::Request.new(env))))
10
+ end
11
+
12
+ def rewrite_request(req)
13
+ req
14
+ end
15
+
16
+ def rewrite_response(res)
17
+ res
18
+ end
19
+
20
+ protected
21
+
22
+ def perform_request(req)
23
+ # Initialize request
24
+ http_request = Net::HTTP.const_get(req.request_method.capitalize).new(req.fullpath)
25
+
26
+ # Setup headers
27
+ http_request.initialize_http_header(http_request_headers(req))
28
+
29
+ # Setup body
30
+ if http_request.request_body_permitted? && req.body
31
+ http_request.body_stream = req.body
32
+ end
33
+
34
+ # Create a streaming response (the actual network communication is deferred, a.k.a. streamed)
35
+ http_response = HttpStreamingResponse.new(http_request, req.host, req.port)
36
+
37
+ [http_response.status, http_response.headers, http_response.body]
38
+ end
39
+
40
+ def http_request_headers(req)
41
+ req.env.reject do |k, v|
42
+ !(/^HTTP_[A-Z_]+$/ === k)
43
+ end.map do |k, v|
44
+ [k.sub(/^HTTP_/, ""), v]
45
+ end.inject({}) do |hash, k_v|
46
+ k, v = k_v
47
+ hash[k] = v
48
+ hash
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rack-proxy}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jacek Becela"]
12
+ s.date = %q{2010-01-08}
13
+ s.description = %q{A Rack app that provides request/response rewriting proxy capabilities with streaming.}
14
+ s.email = %q{jacek.becela@gmail.com}
15
+ s.files = [
16
+ ".gitignore",
17
+ "Rakefile",
18
+ "Readme",
19
+ "VERSION",
20
+ "lib/net_http_hacked.rb",
21
+ "lib/rack/http_streaming_response.rb",
22
+ "lib/rack/proxy.rb",
23
+ "rack-proxy.gemspec",
24
+ "test/http_streaming_response_test.rb",
25
+ "test/net_http_hacked_test.rb",
26
+ "test/rack_proxy_test.rb",
27
+ "test/test_helper.rb"
28
+ ]
29
+ s.homepage = %q{http://github.com/ncr/rack-proxy}
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.3.5}
33
+ s.summary = %q{A request/response rewriting HTTP proxy. A Rack app.}
34
+ s.test_files = [
35
+ "test/http_streaming_response_test.rb",
36
+ "test/net_http_hacked_test.rb",
37
+ "test/rack_proxy_test.rb",
38
+ "test/test_helper.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
46
+ s.add_runtime_dependency(%q<rack>, [">= 0"])
47
+ s.add_development_dependency(%q<rack-test>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<rack>, [">= 0"])
50
+ s.add_dependency(%q<rack-test>, [">= 0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<rack>, [">= 0"])
54
+ s.add_dependency(%q<rack-test>, [">= 0"])
55
+ end
56
+ end
57
+
@@ -0,0 +1,35 @@
1
+ require "test_helper"
2
+ require "rack/http_streaming_response"
3
+
4
+ class HttpStreamingResponseTest < Test::Unit::TestCase
5
+
6
+ def test_streaming
7
+ host, req = "trix.pl", Net::HTTP::Get.new("/")
8
+
9
+ response = Rack::HttpStreamingResponse.new(req, host)
10
+
11
+ # Response status
12
+ assert response.status == "200"
13
+
14
+ # Headers
15
+ headers = response.headers
16
+
17
+ assert headers.size > 0
18
+ assert headers["content-type"] == "text/html"
19
+ assert headers["CoNtEnT-TyPe"] == "text/html"
20
+ assert headers["content-length"].to_i > 0
21
+
22
+ # Body
23
+ chunks = []
24
+ response.body.each do |chunk|
25
+ chunks << chunk
26
+ end
27
+
28
+ assert chunks.size > 0
29
+ chunks.each do |chunk|
30
+ assert chunk.is_a?(String)
31
+ end
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+ require "net_http_hacked"
3
+
4
+ class NetHttpHackedTest < Test::Unit::TestCase
5
+
6
+ def test_net_http_hacked
7
+ req = Net::HTTP::Get.new("/")
8
+ http = Net::HTTP.start("trix.pl", "80")
9
+
10
+ # Response code
11
+ res = http.begin_request_hacked(req)
12
+ assert res.code == "200"
13
+
14
+ # Headers
15
+ headers = {}
16
+ res.each_header { |k, v| headers[k] = v }
17
+
18
+ assert headers.size > 0
19
+ assert headers["content-type"] == "text/html"
20
+ assert headers["content-length"].to_i > 0
21
+
22
+ # Body
23
+ chunks = []
24
+ res.read_body do |chunk|
25
+ chunks << chunk
26
+ end
27
+
28
+ assert chunks.size > 0
29
+ chunks.each do |chunk|
30
+ assert chunk.is_a?(String)
31
+ end
32
+
33
+ http.end_request_hacked
34
+ end
35
+
36
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+ require "rack/proxy"
3
+
4
+ class RackProxyTest < Test::Unit::TestCase
5
+ class TrixProxy < Rack::Proxy
6
+ def rewrite_request(req)
7
+ req.env["HTTP_HOST"] = "trix.pl"
8
+
9
+ req
10
+ end
11
+ end
12
+
13
+ def app
14
+ TrixProxy.new
15
+ end
16
+
17
+ def test_trix
18
+ get "/"
19
+ assert last_response.ok?
20
+ assert /Jacek Becela/ === last_response.body
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ require "rubygems"
2
+ require "test/unit"
3
+
4
+ require "rack"
5
+ require "rack/test"
6
+
7
+ Test::Unit::TestCase.class_eval do
8
+ include Rack::Test::Methods
9
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-proxy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jacek Becela
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-08 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rack
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack-test
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: A Rack app that provides request/response rewriting proxy capabilities with streaming.
36
+ email: jacek.becela@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - .gitignore
45
+ - Rakefile
46
+ - Readme
47
+ - VERSION
48
+ - lib/net_http_hacked.rb
49
+ - lib/rack/http_streaming_response.rb
50
+ - lib/rack/proxy.rb
51
+ - rack-proxy.gemspec
52
+ - test/http_streaming_response_test.rb
53
+ - test/net_http_hacked_test.rb
54
+ - test/rack_proxy_test.rb
55
+ - test/test_helper.rb
56
+ has_rdoc: true
57
+ homepage: http://github.com/ncr/rack-proxy
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=UTF-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.3.5
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: A request/response rewriting HTTP proxy. A Rack app.
84
+ test_files:
85
+ - test/http_streaming_response_test.rb
86
+ - test/net_http_hacked_test.rb
87
+ - test/rack_proxy_test.rb
88
+ - test/test_helper.rb