rack-proxy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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