proxy-server 0.0.5 → 0.0.6

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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- proxy-server (0.0.5)
4
+ proxy-server (0.0.6)
5
+ em-http-request
6
+ em-synchrony
7
+ goliath (= 0.9.2)
5
8
  httpclient
6
9
  json (>= 1.4.6)
7
10
  sinatra (>= 1.2.6)
@@ -11,16 +14,48 @@ GEM
11
14
  remote: http://rubygems.org/
12
15
  specs:
13
16
  addressable (2.2.6)
17
+ async-rack (0.5.1)
18
+ rack (~> 1.1)
14
19
  crack (0.3.1)
15
20
  daemons (1.1.4)
16
21
  diff-lcs (1.1.3)
22
+ em-http-request (1.0.0)
23
+ addressable (>= 2.2.3)
24
+ em-socksify
25
+ eventmachine (>= 1.0.0.beta.3)
26
+ http_parser.rb (>= 0.5.2)
27
+ em-socksify (0.1.0)
28
+ eventmachine
29
+ em-synchrony (1.0.0)
30
+ eventmachine (>= 1.0.0.beta.1)
17
31
  eventmachine (1.0.0.beta.4.1-x86-mingw32)
32
+ goliath (0.9.2)
33
+ async-rack
34
+ em-synchrony (>= 0.3.0.beta.1)
35
+ eventmachine (>= 1.0.0.beta.3)
36
+ http_parser.rb
37
+ http_router (~> 0.8.9)
38
+ log4r
39
+ multi_json
40
+ rack (>= 1.2.2)
41
+ rack-contrib
42
+ rack-respond_to
43
+ http_parser.rb (0.5.3-x86-mingw32)
44
+ http_router (0.8.11)
45
+ rack (>= 1.0.0)
46
+ url_mount (~> 0.2.1)
18
47
  httpclient (2.2.3)
19
48
  json (1.6.1)
49
+ log4r (1.1.9)
20
50
  multi_json (1.0.3)
21
51
  rack (1.3.5)
52
+ rack-accept-media-types (0.9)
53
+ rack-contrib (1.1.0)
54
+ rack (>= 0.9.1)
22
55
  rack-protection (1.1.4)
23
56
  rack
57
+ rack-respond_to (0.9.8)
58
+ rack-accept-media-types (>= 0.6)
24
59
  rack-test (0.6.1)
25
60
  rack (>= 1.0)
26
61
  rake (0.9.2.2)
@@ -45,6 +80,8 @@ GEM
45
80
  eventmachine (>= 0.12.6)
46
81
  rack (>= 1.0.0)
47
82
  tilt (1.3.3)
83
+ url_mount (0.2.1)
84
+ rack
48
85
  webmock (1.7.6)
49
86
  addressable (~> 2.2, > 2.2.5)
50
87
  crack (>= 0.1.7)
@@ -1,12 +1,11 @@
1
- require 'rubygems'
2
- require 'proxy-server'
1
+ require '../lib/proxy-server'
3
2
  require 'rest_client' # you will need to install this via gem install rest-client / bundler etc
3
+ require 'httpclient'
4
4
  require 'json'
5
5
 
6
6
  Thread.abort_on_exception=true
7
7
  Thread.new do
8
- ProxyManager.settings.port = 4983
9
- ProxyManager.run!
8
+ ProxyManager.start :port => 4983
10
9
  end
11
10
 
12
11
  until_proxy_is_running = 3
@@ -76,12 +76,25 @@ class ProxyManager < Sinatra::Base
76
76
 
77
77
  def start_proxy(options)
78
78
  proxy_server = ProxyServer.new(options)
79
- proxy_server.run
79
+ proxy_server.start
80
80
  running_proxy_servers[options[:port]] = proxy_server
81
81
  end
82
82
 
83
83
  def find_proxy_port
84
84
  new_proxy_port = (assigned_proxy_ports.max || ProxyManager::START_PORT) + 1
85
85
  PortProber.above(new_proxy_port)
86
+ end
87
+
88
+ class << self
89
+ def start(options = {})
90
+ require 'thin'
91
+ server = ::Thin::Server.new(
92
+ '0.0.0.0',
93
+ options.fetch(:port, 4985),
94
+ ProxyManager.new
95
+ )
96
+
97
+ server.start
98
+ end
86
99
  end
87
100
  end
@@ -1,16 +1,13 @@
1
- require 'httpclient'
2
- require "thin"
3
- require "rack/content_length"
4
- require "rack/chunked"
5
-
6
- class ProxyServer
1
+ require 'goliath/api'
2
+ require 'goliath/server'
3
+ require 'em-synchrony/em-http'
4
+ class ProxyServer < Goliath::API
7
5
  attr_reader :upstream_proxy, :port
8
6
  attr_reader :requests, :track_requests, :substitute_requests
9
-
10
7
  DEFAULT_PORT = 8080
11
8
 
12
9
  def initialize(options = {})
13
- @upstream_proxy = options[:proxy]
10
+ @upstream_proxy = URI.parse(options[:proxy]) if options[:proxy]
14
11
 
15
12
  @port = options.fetch(:port, DEFAULT_PORT)
16
13
 
@@ -19,17 +16,24 @@ class ProxyServer
19
16
  @track_requests = []
20
17
  end
21
18
 
22
- def http_client
23
- HTTPClient.new :proxy => @upstream_proxy
24
- end
25
-
26
- def run
19
+ def start
20
+ Thread.abort_on_exception = true
21
+ require 'log4r'
27
22
  @proxy_thread = Thread.new do
28
- server = ::Thin::Server.new('0.0.0.0',
29
- self.port,
30
- self)
31
-
32
- server.start
23
+ Goliath.env = :development
24
+ server = Goliath::Server.new('0.0.0.0', self.port)
25
+ server.app = Goliath::Rack::Builder.build(self.class, self)
26
+ server.logger = Log4r::Logger.new 'proxy-server'
27
+
28
+ server.options = {
29
+ :daemonize => false,
30
+ :verbose => true,
31
+ :log_stdout => true,
32
+ :env => :development
33
+ }
34
+ server.start do
35
+ p "Proxy started"
36
+ end
33
37
  end
34
38
  end
35
39
 
@@ -43,46 +47,55 @@ class ProxyServer
43
47
  @substitute_requests.clear
44
48
  end
45
49
 
46
- def call(env)
47
- log_request env
48
-
49
- response = get_substitution(env)
50
- return response unless response.nil?
51
-
50
+ def response(env)
51
+ uri = get_uri env
52
+ track uri if tracking_enabled? uri
53
+ return substitute uri if has_substitute? uri
54
+ request_uri uri
55
+ end
52
56
 
53
- method = env['REQUEST_METHOD']
54
- uri = get_url(env)
55
- body = get_request_body(env)
56
- headers = get_request_headers(env)
57
+ def get_uri(env)
58
+ env['REQUEST_URI'] || "http://#{env['SERVER_NAME']}#{env['PATH_INFO']}#{env['QUERY_STRING'].length > 0 ? '?'+env['QUERY_STRING'] : ''}"
59
+ end
57
60
 
58
- query_string_match = uri.match(/\?(.*)$/)
59
- query_string = query_string_match ? query_string_match[1] : ""
60
- params = get_params(query_string)
61
+ def request_uri(uri)
62
+ options = {
63
+ :redirects => 1
64
+ }
65
+ get_proxy(options)
66
+ client= EM::HttpRequest.new(uri, options)
67
+ request = client.get
68
+ [request.response_header.status, request.response_header, request.response]
69
+ end
61
70
 
62
- response = http_client.request(method, uri, params, body, headers)
63
- [ response.status, response.headers, [response.body] ]
71
+ def get_proxy(options)
72
+ options[:proxy] = {:type => 'http', :host => @upstream_proxy.host, :port => @upstream_proxy.port} if @upstream_proxy
64
73
  end
65
74
 
66
- def get_url(env)
67
- env['REQUEST_URI'] || "http://#{env['SERVER_NAME']}#{env['PATH_INFO']}#{env['QUERY_STRING'].length > 0 ? '?'+env['QUERY_STRING'] : ''}"
75
+ def get_substituted_response(options)
76
+ if options[:body]
77
+ [200, {}, [options[:body]]]
78
+ elsif options[:url]
79
+ request_uri options[:url]
80
+ end
68
81
  end
69
82
 
70
- def get_substitution(env)
83
+ def substitute(uri)
71
84
  @substitute_requests.each do |pattern, options|
72
- if Regexp.new(pattern) =~ get_url(env)
85
+ if Regexp.new(pattern) =~ uri
73
86
  return get_substituted_response(options)
74
87
  end
75
88
  end
76
89
  nil
77
90
  end
78
91
 
79
- def get_substituted_response(options)
80
- if options[:body]
81
- [ 200, {}, [options[:body]] ]
82
- elsif options[:url]
83
- response = @client.get(options[:url])
84
- [ response.status, response.headers, [response.body] ]
92
+ def has_substitute?(uri)
93
+ @substitute_requests.each do |pattern, options|
94
+ if Regexp.new(pattern) =~ uri
95
+ return true
96
+ end
85
97
  end
98
+ false
86
99
  end
87
100
 
88
101
  def substitute_request(pattern, options)
@@ -93,29 +106,17 @@ class ProxyServer
93
106
  @track_requests << pattern
94
107
  end
95
108
 
96
- def get_params(query_string)
97
- query_string.split('&').inject({}) do |hsh, i|
98
- kv = i.split('='); hsh[kv[0]] = kv[1]; hsh
99
- end unless query_string.nil? or query_string.length == 0
100
- end
101
-
102
- def log_request(env)
103
- url = get_url(env)
109
+ def track(uri)
110
+ @requests << uri
104
111
  @track_requests.each do |pattern|
105
- @requests << url if Regexp.new(pattern) =~ url
112
+ @requests << uri if Regexp.new(pattern) =~ uri
106
113
  end
107
114
  end
108
115
 
109
- private
110
- def get_request_body(env)
111
- body = ''
112
- env['rack.input'].each_line {|string| body << string }
113
- body
114
- end
115
-
116
- def get_request_headers(env)
117
- headers = {}
118
- env.each {|k,v| if k =~ /HTTP_(\w+)/ then headers[$1] = v end }
119
- headers
116
+ def tracking_enabled?(uri)
117
+ @track_requests.each do |pattern|
118
+ return true if Regexp.new(pattern) =~ uri
119
+ end
120
+ false
120
121
  end
121
- end
122
+ end
data/proxy-server.gemspec CHANGED
@@ -2,7 +2,7 @@ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'proxy-server'
5
- s.version = '0.0.5'
5
+ s.version = '0.0.6'
6
6
  s.authors = ["Derek Ekins"]
7
7
  s.description = 'Proxy server'
8
8
  s.summary = "proxy-server-#{s.version}"
@@ -15,6 +15,9 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency 'sinatra', '>= 1.2.6'
16
16
  s.add_dependency 'httpclient'
17
17
  s.add_dependency 'thin'
18
+ s.add_dependency 'goliath', '0.9.2'
19
+ s.add_dependency 'em-synchrony'
20
+ s.add_dependency 'em-http-request'
18
21
 
19
22
  s.add_development_dependency 'rake', '>= 0.9.2'
20
23
  s.add_development_dependency 'rspec', '>= 2.7.0'
@@ -1,17 +1,29 @@
1
1
  require_relative '../spec_helper'
2
2
  require_relative '../../lib/proxy/proxy_server'
3
- require 'rack/test'
4
- require 'webmock/rspec'
5
3
 
6
4
  describe ProxyServer do
7
- include Rack::Test::Methods
8
-
9
- let(:app) { ProxyServer.new }
10
-
11
5
  it "can be configured with an upstream proxy" do
12
6
  proxy_uri = 'http://test-proxy:80'
13
7
  proxy = ProxyServer.new :proxy => proxy_uri
14
- proxy.upstream_proxy.should == proxy_uri
8
+ proxy.upstream_proxy.should == URI.parse(proxy_uri)
9
+ end
10
+
11
+ it "should get the proxy settings" do
12
+ proxy_uri = 'http://test-proxy:80'
13
+
14
+ proxy = ProxyServer.new :proxy => proxy_uri
15
+ options = {}
16
+ proxy.get_proxy(options)
17
+ options[:proxy].should == {:type => 'http', :host => 'test-proxy', :port => 80}
18
+ end
19
+
20
+ it "should ignore proxy settings if none specified" do
21
+ proxy = ProxyServer.new
22
+ options = {}
23
+
24
+ proxy.get_proxy(options)
25
+
26
+ options.should_not have_key :proxy
15
27
  end
16
28
 
17
29
  it "can be configured to run on a specific port" do
@@ -25,55 +37,50 @@ describe ProxyServer do
25
37
  proxy.port.should == ProxyServer::DEFAULT_PORT
26
38
  end
27
39
 
28
- it "should allow requests" do
29
- stub_request(:get, "http://www.example.com")
30
-
31
- response = get 'http://www.example.com'
32
- response.status.should == 200
33
- end
40
+ it "should track a request" do
41
+ uri = "http://google.com"
42
+ proxy = ProxyServer.new
34
43
 
35
- it "should allow requests with query strings" do
36
- stub_request(:get, "http://www.example.com?para=value")
44
+ proxy.track uri
37
45
 
38
- response = get "http://www.example.com?para=value"
39
- response.status.should == 200
46
+ proxy.requests.length.should == 1
47
+ proxy.requests.should include uri
40
48
  end
41
49
 
42
- it "can substitute the response of a request with a body of text" do
50
+ it "should determine whether tracking is enabled for a uri" do
51
+ uri = "http://google.com"
43
52
  proxy = ProxyServer.new
44
- expected_response = "this is not what you are looking for"
45
- proxy.substitute_request '.*com', :body => expected_response
46
53
 
47
- browser = Rack::Test::Session.new(Rack::MockSession.new(proxy))
48
- response = browser.get 'http://www.google.com'
49
- response.body.should == expected_response
54
+ proxy.track_request('.*com')
55
+
56
+ proxy.tracking_enabled?('http://www.google.com').should be_true
57
+ proxy.tracking_enabled?('http://www.google.co.uk').should be_false
50
58
  end
51
59
 
52
- it "can substitute the response of a request with another url to call" do
60
+ it "should determine whether there is a substitute for a uri" do
53
61
  proxy = ProxyServer.new
54
- substitute_url = "http://example.com"
55
- expected_response_body = "substitute body"
56
- stub_request(:get, substitute_url).to_return(:body => expected_response_body)
57
- proxy.substitute_request '.*com', :url => substitute_url
58
-
59
- browser = Rack::Test::Session.new(Rack::MockSession.new(proxy))
60
- response = browser.get 'http://www.google.com'
61
- response.body.should == expected_response_body
62
+
63
+ proxy.substitute_request('.*com', :body => 'substitute_response')
64
+
65
+ proxy.has_substitute?('http://www.google.com').should be_true
66
+ proxy.has_substitute?('http://www.google.co.uk').should be_false
62
67
  end
63
68
 
64
- it "tracks a url that matches the pattern" do
69
+ it "should substitute a request body" do
65
70
  proxy = ProxyServer.new
66
- expected_response = "this is not what you are looking for"
67
- proxy.track_request '.*com'
71
+ substitute_response = 'substitute this'
72
+ proxy.substitute_request('.*com', :body => substitute_response)
68
73
 
69
- stub_request(:get, 'http://www.google.com/')
70
- stub_request(:get, 'http://www.google.co.uk/')
74
+ proxy.substitute('http://www.google.com').should == [200, {}, [substitute_response]]
75
+ end
71
76
 
72
- browser = Rack::Test::Session.new(Rack::MockSession.new(proxy))
73
- browser.get 'http://www.google.com/'
74
- browser.get 'http://www.google.co.uk/'
77
+ it "should substitute a request url" do
78
+ proxy = ProxyServer.new
79
+ substitute_url = 'http://www.google.co.uk'
80
+ proxy.substitute_request('.*com', :url => substitute_url)
81
+ proxy.should_receive(:request_uri).with(substitute_url)
75
82
 
76
- proxy.requests.should include('http://www.google.com/')
83
+ proxy.substitute('http://www.google.com')
77
84
  end
78
85
 
79
86
  it "reset causes request tracking to be removed" do
@@ -86,9 +93,27 @@ describe ProxyServer do
86
93
  end
87
94
 
88
95
  it "reset causes request substituting to be removed" do
96
+ proxy = ProxyServer.new
97
+ proxy.substitute_requests['test'] = 'item'
98
+ proxy.reset
99
+ proxy.substitute_requests.length.should == 0
100
+ end
101
+
102
+ context "using response" do
103
+ it "tracks requests" do
89
104
  proxy = ProxyServer.new
90
- proxy.substitute_requests['test'] = 'item'
91
- proxy.reset
92
- proxy.substitute_requests.length.should == 0
105
+ proxy.should_receive(:request_uri).with('http://www.google.com')
106
+
107
+ proxy.track_request '.*google\.com'
108
+ proxy.response('REQUEST_URI' => 'http://www.google.com')
93
109
  end
110
+
111
+ it "substitutes a request" do
112
+ proxy = ProxyServer.new
113
+ substitute_body = 'substitute'
114
+
115
+ proxy.substitute_request '.*google\.com', :body => substitute_body
116
+ proxy.response('REQUEST_URI' => 'http://www.google.com')[2].should == [substitute_body]
117
+ end
118
+ end
94
119
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proxy-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-24 00:00:00.000000000 Z
12
+ date: 2011-11-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &8193912 !ruby/object:Gem::Requirement
16
+ requirement: &8864280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.4.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *8193912
24
+ version_requirements: *8864280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sinatra
27
- requirement: &8192604 !ruby/object:Gem::Requirement
27
+ requirement: &8863992 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.2.6
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *8192604
35
+ version_requirements: *8863992
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: httpclient
38
- requirement: &8190792 !ruby/object:Gem::Requirement
38
+ requirement: &8863764 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *8190792
46
+ version_requirements: *8863764
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: thin
49
- requirement: &8249220 !ruby/object:Gem::Requirement
49
+ requirement: &8863464 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,43 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *8249220
57
+ version_requirements: *8863464
58
+ - !ruby/object:Gem::Dependency
59
+ name: goliath
60
+ requirement: &8863128 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - =
64
+ - !ruby/object:Gem::Version
65
+ version: 0.9.2
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *8863128
69
+ - !ruby/object:Gem::Dependency
70
+ name: em-synchrony
71
+ requirement: &8862828 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *8862828
80
+ - !ruby/object:Gem::Dependency
81
+ name: em-http-request
82
+ requirement: &8862456 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *8862456
58
91
  - !ruby/object:Gem::Dependency
59
92
  name: rake
60
- requirement: &8244744 !ruby/object:Gem::Requirement
93
+ requirement: &8861868 !ruby/object:Gem::Requirement
61
94
  none: false
62
95
  requirements:
63
96
  - - ! '>='
@@ -65,10 +98,10 @@ dependencies:
65
98
  version: 0.9.2
66
99
  type: :development
67
100
  prerelease: false
68
- version_requirements: *8244744
101
+ version_requirements: *8861868
69
102
  - !ruby/object:Gem::Dependency
70
103
  name: rspec
71
- requirement: &8243004 !ruby/object:Gem::Requirement
104
+ requirement: &8877948 !ruby/object:Gem::Requirement
72
105
  none: false
73
106
  requirements:
74
107
  - - ! '>='
@@ -76,10 +109,10 @@ dependencies:
76
109
  version: 2.7.0
77
110
  type: :development
78
111
  prerelease: false
79
- version_requirements: *8243004
112
+ version_requirements: *8877948
80
113
  - !ruby/object:Gem::Dependency
81
114
  name: simplecov
82
- requirement: &8355060 !ruby/object:Gem::Requirement
115
+ requirement: &8877660 !ruby/object:Gem::Requirement
83
116
  none: false
84
117
  requirements:
85
118
  - - ! '>='
@@ -87,10 +120,10 @@ dependencies:
87
120
  version: 0.4.2
88
121
  type: :development
89
122
  prerelease: false
90
- version_requirements: *8355060
123
+ version_requirements: *8877660
91
124
  - !ruby/object:Gem::Dependency
92
125
  name: webmock
93
- requirement: &8353788 !ruby/object:Gem::Requirement
126
+ requirement: &8877312 !ruby/object:Gem::Requirement
94
127
  none: false
95
128
  requirements:
96
129
  - - ! '>='
@@ -98,10 +131,10 @@ dependencies:
98
131
  version: '0'
99
132
  type: :development
100
133
  prerelease: false
101
- version_requirements: *8353788
134
+ version_requirements: *8877312
102
135
  - !ruby/object:Gem::Dependency
103
136
  name: rack-test
104
- requirement: &8350776 !ruby/object:Gem::Requirement
137
+ requirement: &8876820 !ruby/object:Gem::Requirement
105
138
  none: false
106
139
  requirements:
107
140
  - - ! '>='
@@ -109,7 +142,7 @@ dependencies:
109
142
  version: 0.5.7
110
143
  type: :development
111
144
  prerelease: false
112
- version_requirements: *8350776
145
+ version_requirements: *8876820
113
146
  description: Proxy server
114
147
  email: derek@spathi.com
115
148
  executables: []
@@ -153,5 +186,5 @@ rubyforge_project:
153
186
  rubygems_version: 1.8.11
154
187
  signing_key:
155
188
  specification_version: 3
156
- summary: proxy-server-0.0.5
189
+ summary: proxy-server-0.0.6
157
190
  test_files: []