proxy-server 0.0.5 → 0.0.6

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