4
require "webrick/httpproxy"
8
require File.expand_path("../openssl/utils.rb", File.dirname(__FILE__))
10
# test_connect will be skipped
12
require File.expand_path("utils.rb", File.dirname(__FILE__))
14
class TestWEBrickHTTPProxy < Test::Unit::TestCase
16
assert_nil(WEBrick::FakeProxyURI.scheme)
17
assert_nil(WEBrick::FakeProxyURI.host)
18
assert_nil(WEBrick::FakeProxyURI.port)
19
assert_nil(WEBrick::FakeProxyURI.path)
20
assert_nil(WEBrick::FakeProxyURI.userinfo)
21
assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
25
# Testing GET or POST to the proxy server
26
# Note that the proxy server works as the origin server.
29
# client -------> proxy ---+
30
# GET / POST GET / POST
32
proxy_handler_called = request_handler_called = 0
34
:ServerName => "localhost.localdomain",
35
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
36
:RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
38
TestWEBrick.start_httpproxy(config){|server, addr, port|
39
server.mount_proc("/"){|req, res|
40
res.body = "#{req.request_method} #{req.path} #{req.body}"
42
http = Net::HTTP.new(addr, port, addr, port)
44
req = Net::HTTP::Get.new("/")
45
http.request(req){|res|
46
assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
47
assert_equal("GET / ", res.body)
49
assert_equal(1, proxy_handler_called)
50
assert_equal(2, request_handler_called)
52
req = Net::HTTP::Head.new("/")
53
http.request(req){|res|
54
assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
57
assert_equal(2, proxy_handler_called)
58
assert_equal(4, request_handler_called)
60
req = Net::HTTP::Post.new("/")
61
req.body = "post-data"
62
http.request(req){|res|
63
assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
64
assert_equal("POST / post-data", res.body)
66
assert_equal(3, proxy_handler_called)
67
assert_equal(6, request_handler_called)
72
# Testing GET or POST to the proxy server without proxy request.
74
# client -------> proxy
77
proxy_handler_called = request_handler_called = 0
79
:ServerName => "localhost.localdomain",
80
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
81
:RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
83
TestWEBrick.start_httpproxy(config){|server, addr, port|
84
server.mount_proc("/"){|req, res|
85
res.body = "#{req.request_method} #{req.path} #{req.body}"
87
http = Net::HTTP.new(addr, port)
89
req = Net::HTTP::Get.new("/")
90
http.request(req){|res|
91
assert_nil(res["via"])
92
assert_equal("GET / ", res.body)
94
assert_equal(0, proxy_handler_called)
95
assert_equal(1, request_handler_called)
97
req = Net::HTTP::Head.new("/")
98
http.request(req){|res|
99
assert_nil(res["via"])
102
assert_equal(0, proxy_handler_called)
103
assert_equal(2, request_handler_called)
105
req = Net::HTTP::Post.new("/")
106
req.body = "post-data"
107
http.request(req){|res|
108
assert_nil(res["via"])
109
assert_equal("POST / post-data", res.body)
111
assert_equal(0, proxy_handler_called)
112
assert_equal(3, request_handler_called)
116
def make_certificate(key, cn)
117
subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
119
["keyUsage", "keyEncipherment,digitalSignature", true],
121
cert = OpenSSL::TestUtils.issue_cert(
122
subject, key, 1, Time.now, Time.now + 3600, exts,
123
nil, nil, OpenSSL::Digest::SHA1.new
129
# Testing CONNECT to proxy server
131
# client -----------> proxy -----------> https
132
# 1. CONNECT establish TCP
133
# 2. ---- establish SSL session --->
134
# 3. ------- GET or POST ---------->
136
key = OpenSSL::TestUtils::TEST_KEY_RSA1024
137
cert = make_certificate(key, "127.0.0.1")
140
:ServerName => "localhost",
141
:SSLCertificate => cert,
142
:SSLPrivateKey => key,
145
:ServerName => "localhost.localdomain",
146
:RequestHandler => Proc.new{|req, res|
147
assert_equal("CONNECT", req.request_method)
150
TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
151
s_server.mount_proc("/"){|req, res|
152
res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
154
TestWEBrick.start_httpproxy(config){|server, addr, port|
155
http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
157
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
158
store_ctx.current_cert.to_der == cert.to_der
161
req = Net::HTTP::Get.new("/")
162
http.request(req){|res|
163
assert_equal("SSL GET / ", res.body)
166
req = Net::HTTP::Post.new("/")
167
req.body = "post-data"
168
http.request(req){|res|
169
assert_equal("SSL POST / post-data", res.body)
173
end if defined?(OpenSSL)
175
def test_upstream_proxy
176
# Testing GET or POST through the upstream proxy server
177
# Note that the upstream proxy server works as the origin server.
180
# client -------> proxy -------> proxy ---+
181
# GET / POST GET / POST GET / POST
183
up_proxy_handler_called = up_request_handler_called = 0
184
proxy_handler_called = request_handler_called = 0
186
:ServerName => "localhost.localdomain",
187
:ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
188
:RequestHandler => Proc.new{|req, res| up_request_handler_called += 1}
190
TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port|
191
up_server.mount_proc("/"){|req, res|
192
res.body = "#{req.request_method} #{req.path} #{req.body}"
195
:ServerName => "localhost.localdomain",
196
:ProxyURI => URI.parse("http://localhost:#{up_port}"),
197
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
198
:RequestHandler => Proc.new{|req, res| request_handler_called += 1},
200
TestWEBrick.start_httpproxy(config){|server, addr, port|
201
http = Net::HTTP.new(up_addr, up_port, addr, port)
203
req = Net::HTTP::Get.new("/")
204
http.request(req){|res|
205
via = res["via"].split(/,\s+/)
206
assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
207
assert(via.include?("1.1 localhost.localdomain:#{port}"))
208
assert_equal("GET / ", res.body)
210
assert_equal(1, up_proxy_handler_called)
211
assert_equal(2, up_request_handler_called)
212
assert_equal(1, proxy_handler_called)
213
assert_equal(1, request_handler_called)
215
req = Net::HTTP::Head.new("/")
216
http.request(req){|res|
217
via = res["via"].split(/,\s+/)
218
assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
219
assert(via.include?("1.1 localhost.localdomain:#{port}"))
222
assert_equal(2, up_proxy_handler_called)
223
assert_equal(4, up_request_handler_called)
224
assert_equal(2, proxy_handler_called)
225
assert_equal(2, request_handler_called)
227
req = Net::HTTP::Post.new("/")
228
req.body = "post-data"
229
http.request(req){|res|
230
via = res["via"].split(/,\s+/)
231
assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
232
assert(via.include?("1.1 localhost.localdomain:#{port}"))
233
assert_equal("POST / post-data", res.body)
235
assert_equal(3, up_proxy_handler_called)
236
assert_equal(6, up_request_handler_called)
237
assert_equal(3, proxy_handler_called)
238
assert_equal(3, request_handler_called)
241
# Testing CONNECT to the upstream proxy server
243
# client -------> proxy -------> proxy -------> https
244
# 1. CONNECT CONNECT establish TCP
245
# 2. -------- establish SSL session ------>
246
# 3. ---------- GET or POST -------------->
248
key = OpenSSL::TestUtils::TEST_KEY_RSA1024
249
cert = make_certificate(key, "127.0.0.1")
252
:ServerName => "localhost",
253
:SSLCertificate => cert,
254
:SSLPrivateKey => key,
256
TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
257
s_server.mount_proc("/"){|req, res|
258
res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
260
http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
262
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
263
store_ctx.current_cert.to_der == cert.to_der
266
req = Net::HTTP::Get.new("/")
267
http.request(req){|res|
268
assert_equal("SSL GET / ", res.body)
271
req = Net::HTTP::Post.new("/")
272
req.body = "post-data"
273
http.request(req){|res|
274
assert_equal("SSL POST / post-data", res.body)