webrick 1.3.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of webrick might be problematic. Click here for more details.

Files changed (63) hide show
  1. data/README.txt +21 -0
  2. data/lib/webrick.rb +227 -0
  3. data/lib/webrick/accesslog.rb +151 -0
  4. data/lib/webrick/cgi.rb +260 -0
  5. data/lib/webrick/compat.rb +35 -0
  6. data/lib/webrick/config.rb +121 -0
  7. data/lib/webrick/cookie.rb +110 -0
  8. data/lib/webrick/htmlutils.rb +28 -0
  9. data/lib/webrick/httpauth.rb +95 -0
  10. data/lib/webrick/httpauth/authenticator.rb +112 -0
  11. data/lib/webrick/httpauth/basicauth.rb +108 -0
  12. data/lib/webrick/httpauth/digestauth.rb +392 -0
  13. data/lib/webrick/httpauth/htdigest.rb +128 -0
  14. data/lib/webrick/httpauth/htgroup.rb +93 -0
  15. data/lib/webrick/httpauth/htpasswd.rb +121 -0
  16. data/lib/webrick/httpauth/userdb.rb +52 -0
  17. data/lib/webrick/httpproxy.rb +305 -0
  18. data/lib/webrick/httprequest.rb +461 -0
  19. data/lib/webrick/httpresponse.rb +399 -0
  20. data/lib/webrick/https.rb +64 -0
  21. data/lib/webrick/httpserver.rb +264 -0
  22. data/lib/webrick/httpservlet.rb +22 -0
  23. data/lib/webrick/httpservlet/abstract.rb +153 -0
  24. data/lib/webrick/httpservlet/cgi_runner.rb +46 -0
  25. data/lib/webrick/httpservlet/cgihandler.rb +108 -0
  26. data/lib/webrick/httpservlet/erbhandler.rb +87 -0
  27. data/lib/webrick/httpservlet/filehandler.rb +470 -0
  28. data/lib/webrick/httpservlet/prochandler.rb +33 -0
  29. data/lib/webrick/httpstatus.rb +184 -0
  30. data/lib/webrick/httputils.rb +394 -0
  31. data/lib/webrick/httpversion.rb +49 -0
  32. data/lib/webrick/log.rb +136 -0
  33. data/lib/webrick/server.rb +218 -0
  34. data/lib/webrick/ssl.rb +127 -0
  35. data/lib/webrick/utils.rb +241 -0
  36. data/lib/webrick/version.rb +13 -0
  37. data/sample/webrick/demo-app.rb +66 -0
  38. data/sample/webrick/demo-multipart.cgi +12 -0
  39. data/sample/webrick/demo-servlet.rb +6 -0
  40. data/sample/webrick/demo-urlencoded.cgi +12 -0
  41. data/sample/webrick/hello.cgi +11 -0
  42. data/sample/webrick/hello.rb +8 -0
  43. data/sample/webrick/httpd.rb +23 -0
  44. data/sample/webrick/httpproxy.rb +25 -0
  45. data/sample/webrick/httpsd.rb +33 -0
  46. data/test/openssl/utils.rb +313 -0
  47. data/test/ruby/envutil.rb +208 -0
  48. data/test/webrick/test_cgi.rb +134 -0
  49. data/test/webrick/test_cookie.rb +131 -0
  50. data/test/webrick/test_filehandler.rb +285 -0
  51. data/test/webrick/test_httpauth.rb +167 -0
  52. data/test/webrick/test_httpproxy.rb +282 -0
  53. data/test/webrick/test_httprequest.rb +411 -0
  54. data/test/webrick/test_httpresponse.rb +49 -0
  55. data/test/webrick/test_httpserver.rb +305 -0
  56. data/test/webrick/test_httputils.rb +96 -0
  57. data/test/webrick/test_httpversion.rb +40 -0
  58. data/test/webrick/test_server.rb +67 -0
  59. data/test/webrick/test_utils.rb +64 -0
  60. data/test/webrick/utils.rb +58 -0
  61. data/test/webrick/webrick.cgi +36 -0
  62. data/test/webrick/webrick_long_filename.cgi +36 -0
  63. metadata +106 -0
@@ -0,0 +1,167 @@
1
+ require "test/unit"
2
+ require "net/http"
3
+ require "tempfile"
4
+ require "webrick"
5
+ require "webrick/httpauth/basicauth"
6
+ require_relative "utils"
7
+
8
+ class TestWEBrickHTTPAuth < Test::Unit::TestCase
9
+ def test_basic_auth
10
+ TestWEBrick.start_httpserver{|server, addr, port, log|
11
+ realm = "WEBrick's realm"
12
+ path = "/basic_auth"
13
+
14
+ server.mount_proc(path){|req, res|
15
+ WEBrick::HTTPAuth.basic_auth(req, res, realm){|user, pass|
16
+ user == "webrick" && pass == "supersecretpassword"
17
+ }
18
+ res.body = "hoge"
19
+ }
20
+ http = Net::HTTP.new(addr, port)
21
+ g = Net::HTTP::Get.new(path)
22
+ g.basic_auth("webrick", "supersecretpassword")
23
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
24
+ g.basic_auth("webrick", "not super")
25
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
26
+ }
27
+ end
28
+
29
+ def test_basic_auth2
30
+ TestWEBrick.start_httpserver{|server, addr, port, log|
31
+ realm = "WEBrick's realm"
32
+ path = "/basic_auth2"
33
+
34
+ tmpfile = Tempfile.new("test_webrick_auth")
35
+ tmpfile.close
36
+ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
37
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
38
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
39
+ tmp_pass.flush
40
+
41
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
42
+ users = []
43
+ htpasswd.each{|user, pass| users << user }
44
+ assert_equal(2, users.size, log.call)
45
+ assert(users.member?("webrick"), log.call)
46
+ assert(users.member?("foo"), log.call)
47
+
48
+ server.mount_proc(path){|req, res|
49
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
50
+ :Realm => realm, :UserDB => htpasswd,
51
+ :Logger => server.logger
52
+ )
53
+ auth.authenticate(req, res)
54
+ res.body = "hoge"
55
+ }
56
+ http = Net::HTTP.new(addr, port)
57
+ g = Net::HTTP::Get.new(path)
58
+ g.basic_auth("webrick", "supersecretpassword")
59
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
60
+ g.basic_auth("webrick", "not super")
61
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
62
+ }
63
+ end
64
+
65
+ def test_basic_auth3
66
+ tmpfile = Tempfile.new("test_webrick_auth")
67
+ tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
68
+ tmpfile.flush
69
+ assert_raise(NotImplementedError){
70
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
71
+ }
72
+ tmpfile.close(true)
73
+
74
+ tmpfile = Tempfile.new("test_webrick_auth")
75
+ tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
76
+ tmpfile.flush
77
+ assert_raise(NotImplementedError){
78
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
79
+ }
80
+ tmpfile.close(true)
81
+ end
82
+
83
+ DIGESTRES_ = /
84
+ ([a-zA-z\-]+)
85
+ [\s\t]*(?:\r\n[\s\t]*)*
86
+ =
87
+ [\s\t]*(?:\r\n[\s\t]*)*
88
+ (?:
89
+ "((?:[^"]+|\\[\x00-\x7F])*)" |
90
+ ([!\#$%&'*+\-.0-9A-Z^_`a-z|~]+)
91
+ )/x
92
+
93
+ def test_digest_auth
94
+ TestWEBrick.start_httpserver{|server, addr, port, log|
95
+ realm = "WEBrick's realm"
96
+ path = "/digest_auth"
97
+
98
+ tmpfile = Tempfile.new("test_webrick_auth")
99
+ tmpfile.close
100
+ tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
101
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
102
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
103
+ tmp_pass.flush
104
+
105
+ htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
106
+ users = []
107
+ htdigest.each{|user, pass| users << user }
108
+ assert_equal(2, users.size, log.call)
109
+ assert(users.member?("webrick"), log.call)
110
+ assert(users.member?("foo"), log.call)
111
+
112
+ auth = WEBrick::HTTPAuth::DigestAuth.new(
113
+ :Realm => realm, :UserDB => htdigest,
114
+ :Algorithm => 'MD5',
115
+ :Logger => server.logger
116
+ )
117
+ server.mount_proc(path){|req, res|
118
+ auth.authenticate(req, res)
119
+ res.body = "hoge"
120
+ }
121
+
122
+ Net::HTTP.start(addr, port) do |http|
123
+ g = Net::HTTP::Get.new(path)
124
+ params = {}
125
+ http.request(g) do |res|
126
+ assert_equal('401', res.code, log.call)
127
+ res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
128
+ params[key.downcase] = token || quoted.delete('\\')
129
+ end
130
+ params['uri'] = "http://#{addr}:#{port}#{path}"
131
+ end
132
+
133
+ g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
134
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
135
+
136
+ params['algorithm'].downcase! #4936
137
+ g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
138
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
139
+
140
+ g['Authorization'] = credentials_for_request('webrick', "not super", params)
141
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
142
+ end
143
+ }
144
+ end
145
+
146
+ private
147
+ def credentials_for_request(user, password, params)
148
+ cnonce = "hoge"
149
+ nonce_count = 1
150
+ ha1 = "#{user}:#{params['realm']}:#{password}"
151
+ ha2 = "GET:#{params['uri']}"
152
+ request_digest =
153
+ "#{Digest::MD5.hexdigest(ha1)}:" \
154
+ "#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \
155
+ "#{Digest::MD5.hexdigest(ha2)}"
156
+ "Digest username=\"#{user}\"" \
157
+ ", realm=\"#{params['realm']}\"" \
158
+ ", nonce=\"#{params['nonce']}\"" \
159
+ ", uri=\"#{params['uri']}\"" \
160
+ ", qop=#{params['qop']}" \
161
+ ", nc=#{'%08x' % nonce_count}" \
162
+ ", cnonce=\"#{cnonce}\"" \
163
+ ", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \
164
+ ", opaque=\"#{params['opaque']}\"" \
165
+ ", algorithm=#{params['algorithm']}"
166
+ end
167
+ end
@@ -0,0 +1,282 @@
1
+ require "test/unit"
2
+ require "net/http"
3
+ require "webrick"
4
+ require "webrick/httpproxy"
5
+ begin
6
+ require "webrick/ssl"
7
+ require "net/https"
8
+ require File.expand_path("../openssl/utils.rb", File.dirname(__FILE__))
9
+ rescue LoadError
10
+ # test_connect will be skipped
11
+ end
12
+ require File.expand_path("utils.rb", File.dirname(__FILE__))
13
+
14
+ class TestWEBrickHTTPProxy < Test::Unit::TestCase
15
+ def test_fake_proxy
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 }
22
+ end
23
+
24
+ def test_proxy
25
+ # Testing GET or POST to the proxy server
26
+ # Note that the proxy server works as the origin server.
27
+ # +------+
28
+ # V |
29
+ # client -------> proxy ---+
30
+ # GET / POST GET / POST
31
+ #
32
+ proxy_handler_called = request_handler_called = 0
33
+ config = {
34
+ :ServerName => "localhost.localdomain",
35
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
36
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
37
+ }
38
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
39
+ server.mount_proc("/"){|req, res|
40
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
41
+ }
42
+ http = Net::HTTP.new(addr, port, addr, port)
43
+
44
+ req = Net::HTTP::Get.new("/")
45
+ http.request(req){|res|
46
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
47
+ assert_equal("GET / ", res.body, log.call)
48
+ }
49
+ assert_equal(1, proxy_handler_called, log.call)
50
+ assert_equal(2, request_handler_called, log.call)
51
+
52
+ req = Net::HTTP::Head.new("/")
53
+ http.request(req){|res|
54
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
55
+ assert_nil(res.body, log.call)
56
+ }
57
+ assert_equal(2, proxy_handler_called, log.call)
58
+ assert_equal(4, request_handler_called, log.call)
59
+
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"], log.call)
64
+ assert_equal("POST / post-data", res.body, log.call)
65
+ }
66
+ assert_equal(3, proxy_handler_called, log.call)
67
+ assert_equal(6, request_handler_called, log.call)
68
+ }
69
+ end
70
+
71
+ def test_no_proxy
72
+ # Testing GET or POST to the proxy server without proxy request.
73
+ #
74
+ # client -------> proxy
75
+ # GET / POST
76
+ #
77
+ proxy_handler_called = request_handler_called = 0
78
+ config = {
79
+ :ServerName => "localhost.localdomain",
80
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
81
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
82
+ }
83
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
84
+ server.mount_proc("/"){|req, res|
85
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
86
+ }
87
+ http = Net::HTTP.new(addr, port)
88
+
89
+ req = Net::HTTP::Get.new("/")
90
+ http.request(req){|res|
91
+ assert_nil(res["via"], log.call)
92
+ assert_equal("GET / ", res.body, log.call)
93
+ }
94
+ assert_equal(0, proxy_handler_called, log.call)
95
+ assert_equal(1, request_handler_called, log.call)
96
+
97
+ req = Net::HTTP::Head.new("/")
98
+ http.request(req){|res|
99
+ assert_nil(res["via"], log.call)
100
+ assert_nil(res.body, log.call)
101
+ }
102
+ assert_equal(0, proxy_handler_called, log.call)
103
+ assert_equal(2, request_handler_called, log.call)
104
+
105
+ req = Net::HTTP::Post.new("/")
106
+ req.body = "post-data"
107
+ http.request(req){|res|
108
+ assert_nil(res["via"], log.call)
109
+ assert_equal("POST / post-data", res.body, log.call)
110
+ }
111
+ assert_equal(0, proxy_handler_called, log.call)
112
+ assert_equal(3, request_handler_called, log.call)
113
+ }
114
+ end
115
+
116
+ def make_certificate(key, cn)
117
+ subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
118
+ exts = [
119
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
120
+ ]
121
+ cert = OpenSSL::TestUtils.issue_cert(
122
+ subject, key, 1, Time.now, Time.now + 3600, exts,
123
+ nil, nil, OpenSSL::Digest::SHA1.new
124
+ )
125
+ return cert
126
+ end
127
+
128
+ def test_connect
129
+ # Testing CONNECT to proxy server
130
+ #
131
+ # client -----------> proxy -----------> https
132
+ # 1. CONNECT establish TCP
133
+ # 2. ---- establish SSL session --->
134
+ # 3. ------- GET or POST ---------->
135
+ #
136
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
137
+ cert = make_certificate(key, "127.0.0.1")
138
+ s_config = {
139
+ :SSLEnable =>true,
140
+ :ServerName => "localhost",
141
+ :SSLCertificate => cert,
142
+ :SSLPrivateKey => key,
143
+ }
144
+ config = {
145
+ :ServerName => "localhost.localdomain",
146
+ :RequestCallback => Proc.new{|req, res|
147
+ assert_equal("CONNECT", req.request_method)
148
+ },
149
+ }
150
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
151
+ s_server.mount_proc("/"){|req, res|
152
+ res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
153
+ }
154
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
155
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
156
+ http.use_ssl = true
157
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
158
+ store_ctx.current_cert.to_der == cert.to_der
159
+ end
160
+
161
+ req = Net::HTTP::Get.new("/")
162
+ http.request(req){|res|
163
+ assert_equal("SSL GET / ", res.body, s_log.call + log.call)
164
+ }
165
+
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, s_log.call + log.call)
170
+ }
171
+ }
172
+ }
173
+ end if defined?(OpenSSL)
174
+
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.
178
+ # +------+
179
+ # V |
180
+ # client -------> proxy -------> proxy ---+
181
+ # GET / POST GET / POST GET / POST
182
+ #
183
+ up_proxy_handler_called = up_request_handler_called = 0
184
+ proxy_handler_called = request_handler_called = 0
185
+ up_config = {
186
+ :ServerName => "localhost.localdomain",
187
+ :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
188
+ :RequestCallback => Proc.new{|req, res| up_request_handler_called += 1}
189
+ }
190
+ TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
191
+ up_server.mount_proc("/"){|req, res|
192
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
193
+ }
194
+ config = {
195
+ :ServerName => "localhost.localdomain",
196
+ :ProxyURI => URI.parse("http://localhost:#{up_port}"),
197
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
198
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1},
199
+ }
200
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
201
+ http = Net::HTTP.new(up_addr, up_port, addr, port)
202
+
203
+ req = Net::HTTP::Get.new("/")
204
+ http.request(req){|res|
205
+ skip res.message unless res.code == '200'
206
+ via = res["via"].split(/,\s+/)
207
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
208
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
209
+ assert_equal("GET / ", res.body)
210
+ }
211
+ assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
212
+ assert_equal(2, up_request_handler_called, up_log.call + log.call)
213
+ assert_equal(1, proxy_handler_called, up_log.call + log.call)
214
+ assert_equal(1, request_handler_called, up_log.call + log.call)
215
+
216
+ req = Net::HTTP::Head.new("/")
217
+ http.request(req){|res|
218
+ via = res["via"].split(/,\s+/)
219
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
220
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
221
+ assert_nil(res.body, up_log.call + log.call)
222
+ }
223
+ assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
224
+ assert_equal(4, up_request_handler_called, up_log.call + log.call)
225
+ assert_equal(2, proxy_handler_called, up_log.call + log.call)
226
+ assert_equal(2, request_handler_called, up_log.call + log.call)
227
+
228
+ req = Net::HTTP::Post.new("/")
229
+ req.body = "post-data"
230
+ http.request(req){|res|
231
+ via = res["via"].split(/,\s+/)
232
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
233
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
234
+ assert_equal("POST / post-data", res.body, up_log.call + log.call)
235
+ }
236
+ assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
237
+ assert_equal(6, up_request_handler_called, up_log.call + log.call)
238
+ assert_equal(3, proxy_handler_called, up_log.call + log.call)
239
+ assert_equal(3, request_handler_called, up_log.call + log.call)
240
+
241
+ if defined?(OpenSSL)
242
+ # Testing CONNECT to the upstream proxy server
243
+ #
244
+ # client -------> proxy -------> proxy -------> https
245
+ # 1. CONNECT CONNECT establish TCP
246
+ # 2. -------- establish SSL session ------>
247
+ # 3. ---------- GET or POST -------------->
248
+ #
249
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
250
+ cert = make_certificate(key, "127.0.0.1")
251
+ s_config = {
252
+ :SSLEnable =>true,
253
+ :ServerName => "localhost",
254
+ :SSLCertificate => cert,
255
+ :SSLPrivateKey => key,
256
+ }
257
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
258
+ s_server.mount_proc("/"){|req2, res|
259
+ res.body = "SSL #{req2.request_method} #{req2.path} #{req2.body}"
260
+ }
261
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
262
+ http.use_ssl = true
263
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
264
+ store_ctx.current_cert.to_der == cert.to_der
265
+ end
266
+
267
+ req2 = Net::HTTP::Get.new("/")
268
+ http.request(req2){|res|
269
+ assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
270
+ }
271
+
272
+ req2 = Net::HTTP::Post.new("/")
273
+ req2.body = "post-data"
274
+ http.request(req2){|res|
275
+ assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
276
+ }
277
+ }
278
+ end
279
+ }
280
+ }
281
+ end
282
+ end
@@ -0,0 +1,411 @@
1
+ require "webrick"
2
+ require "stringio"
3
+ require "test/unit"
4
+
5
+ class TestWEBrickHTTPRequest < Test::Unit::TestCase
6
+ def test_simple_request
7
+ msg = <<-_end_of_message_
8
+ GET /
9
+ _end_of_message_
10
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
11
+ req.parse(StringIO.new(msg))
12
+ assert(req.meta_vars) # fails if @header was not initialized and iteration is attempted on the nil reference
13
+ end
14
+
15
+ def test_parse_09
16
+ msg = <<-_end_of_message_
17
+ GET /
18
+ foobar # HTTP/0.9 request don't have header nor entity body.
19
+ _end_of_message_
20
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
21
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
22
+ assert_equal("GET", req.request_method)
23
+ assert_equal("/", req.unparsed_uri)
24
+ assert_equal(WEBrick::HTTPVersion.new("0.9"), req.http_version)
25
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
26
+ assert_equal(80, req.port)
27
+ assert_equal(false, req.keep_alive?)
28
+ assert_equal(nil, req.body)
29
+ assert(req.query.empty?)
30
+ end
31
+
32
+ def test_parse_10
33
+ msg = <<-_end_of_message_
34
+ GET / HTTP/1.0
35
+
36
+ _end_of_message_
37
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
38
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
39
+ assert_equal("GET", req.request_method)
40
+ assert_equal("/", req.unparsed_uri)
41
+ assert_equal(WEBrick::HTTPVersion.new("1.0"), req.http_version)
42
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
43
+ assert_equal(80, req.port)
44
+ assert_equal(false, req.keep_alive?)
45
+ assert_equal(nil, req.body)
46
+ assert(req.query.empty?)
47
+ end
48
+
49
+ def test_parse_11
50
+ msg = <<-_end_of_message_
51
+ GET /path HTTP/1.1
52
+
53
+ _end_of_message_
54
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
55
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
56
+ assert_equal("GET", req.request_method)
57
+ assert_equal("/path", req.unparsed_uri)
58
+ assert_equal("", req.script_name)
59
+ assert_equal("/path", req.path_info)
60
+ assert_equal(WEBrick::HTTPVersion.new("1.1"), req.http_version)
61
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
62
+ assert_equal(80, req.port)
63
+ assert_equal(true, req.keep_alive?)
64
+ assert_equal(nil, req.body)
65
+ assert(req.query.empty?)
66
+ end
67
+
68
+ def test_request_uri_too_large
69
+ msg = <<-_end_of_message_
70
+ GET /#{"a"*2084} HTTP/1.1
71
+ _end_of_message_
72
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
73
+ assert_raise(WEBrick::HTTPStatus::RequestURITooLarge){
74
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
75
+ }
76
+ end
77
+
78
+ def test_parse_headers
79
+ msg = <<-_end_of_message_
80
+ GET /path HTTP/1.1
81
+ Host: test.ruby-lang.org:8080
82
+ Connection: close
83
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
84
+ text/html;level=2;q=0.4, */*;q=0.5
85
+ Accept-Encoding: compress;q=0.5
86
+ Accept-Encoding: gzip;q=1.0, identity; q=0.4, *;q=0
87
+ Accept-Language: en;q=0.5, *; q=0
88
+ Accept-Language: ja
89
+ Content-Type: text/plain
90
+ Content-Length: 7
91
+ X-Empty-Header:
92
+
93
+ foobar
94
+ _end_of_message_
95
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
96
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
97
+ assert_equal(
98
+ URI.parse("http://test.ruby-lang.org:8080/path"), req.request_uri)
99
+ assert_equal("test.ruby-lang.org", req.host)
100
+ assert_equal(8080, req.port)
101
+ assert_equal(false, req.keep_alive?)
102
+ assert_equal(
103
+ %w(text/html;level=1 text/html */* text/html;level=2 text/*),
104
+ req.accept)
105
+ assert_equal(%w(gzip compress identity *), req.accept_encoding)
106
+ assert_equal(%w(ja en *), req.accept_language)
107
+ assert_equal(7, req.content_length)
108
+ assert_equal("text/plain", req.content_type)
109
+ assert_equal("foobar\n", req.body)
110
+ assert_equal("", req["x-empty-header"])
111
+ assert_equal(nil, req["x-no-header"])
112
+ assert(req.query.empty?)
113
+ end
114
+
115
+ def test_parse_header2()
116
+ msg = <<-_end_of_message_
117
+ POST /foo/bar/../baz?q=a HTTP/1.0
118
+ Content-Length: 9
119
+ User-Agent:
120
+ FOO BAR
121
+ BAZ
122
+
123
+ hogehoge
124
+ _end_of_message_
125
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
126
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
127
+ assert_equal("POST", req.request_method)
128
+ assert_equal("/foo/baz", req.path)
129
+ assert_equal("", req.script_name)
130
+ assert_equal("/foo/baz", req.path_info)
131
+ assert_equal("9", req['content-length'])
132
+ assert_equal("FOO BAR BAZ", req['user-agent'])
133
+ assert_equal("hogehoge\n", req.body)
134
+ end
135
+
136
+ def test_parse_headers3
137
+ msg = <<-_end_of_message_
138
+ GET /path HTTP/1.1
139
+ Host: test.ruby-lang.org
140
+
141
+ _end_of_message_
142
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
143
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
144
+ assert_equal(URI.parse("http://test.ruby-lang.org/path"), req.request_uri)
145
+ assert_equal("test.ruby-lang.org", req.host)
146
+ assert_equal(80, req.port)
147
+
148
+ msg = <<-_end_of_message_
149
+ GET /path HTTP/1.1
150
+ Host: 192.168.1.1
151
+
152
+ _end_of_message_
153
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
154
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
155
+ assert_equal(URI.parse("http://192.168.1.1/path"), req.request_uri)
156
+ assert_equal("192.168.1.1", req.host)
157
+ assert_equal(80, req.port)
158
+
159
+ msg = <<-_end_of_message_
160
+ GET /path HTTP/1.1
161
+ Host: [fe80::208:dff:feef:98c7]
162
+
163
+ _end_of_message_
164
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
165
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
166
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]/path"),
167
+ req.request_uri)
168
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
169
+ assert_equal(80, req.port)
170
+
171
+ msg = <<-_end_of_message_
172
+ GET /path HTTP/1.1
173
+ Host: 192.168.1.1:8080
174
+
175
+ _end_of_message_
176
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
177
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
178
+ assert_equal(URI.parse("http://192.168.1.1:8080/path"), req.request_uri)
179
+ assert_equal("192.168.1.1", req.host)
180
+ assert_equal(8080, req.port)
181
+
182
+ msg = <<-_end_of_message_
183
+ GET /path HTTP/1.1
184
+ Host: [fe80::208:dff:feef:98c7]:8080
185
+
186
+ _end_of_message_
187
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
188
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
189
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]:8080/path"),
190
+ req.request_uri)
191
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
192
+ assert_equal(8080, req.port)
193
+ end
194
+
195
+ def test_parse_get_params
196
+ param = "foo=1;foo=2;foo=3;bar=x"
197
+ msg = <<-_end_of_message_
198
+ GET /path?#{param} HTTP/1.1
199
+ Host: test.ruby-lang.org:8080
200
+
201
+ _end_of_message_
202
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
203
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
204
+ query = req.query
205
+ assert_equal("1", query["foo"])
206
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
207
+ assert_equal(["1", "2", "3"], query["foo"].list)
208
+ assert_equal("x", query["bar"])
209
+ assert_equal(["x"], query["bar"].list)
210
+ end
211
+
212
+ def test_parse_post_params
213
+ param = "foo=1;foo=2;foo=3;bar=x"
214
+ msg = <<-_end_of_message_
215
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
216
+ Host: test.ruby-lang.org:8080
217
+ Content-Length: #{param.size}
218
+ Content-Type: application/x-www-form-urlencoded
219
+
220
+ #{param}
221
+ _end_of_message_
222
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
223
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
224
+ query = req.query
225
+ assert_equal("1", query["foo"])
226
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
227
+ assert_equal(["1", "2", "3"], query["foo"].list)
228
+ assert_equal("x", query["bar"])
229
+ assert_equal(["x"], query["bar"].list)
230
+ end
231
+
232
+ def test_chunked
233
+ crlf = "\x0d\x0a"
234
+ msg = <<-_end_of_message_
235
+ POST /path HTTP/1.1
236
+ Host: test.ruby-lang.org:8080
237
+ Transfer-Encoding: chunked
238
+
239
+ _end_of_message_
240
+ msg.gsub!(/^ {6}/, "")
241
+ open(__FILE__){|io|
242
+ while chunk = io.read(100)
243
+ msg << chunk.size.to_s(16) << crlf
244
+ msg << chunk << crlf
245
+ end
246
+ }
247
+ msg << "0" << crlf
248
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
249
+ req.parse(StringIO.new(msg))
250
+ assert_equal(File.read(__FILE__), req.body)
251
+ end
252
+
253
+ def test_forwarded
254
+ msg = <<-_end_of_message_
255
+ GET /foo HTTP/1.1
256
+ Host: localhost:10080
257
+ User-Agent: w3m/0.5.2
258
+ X-Forwarded-For: 123.123.123.123
259
+ X-Forwarded-Host: forward.example.com
260
+ X-Forwarded-Server: server.example.com
261
+ Connection: Keep-Alive
262
+
263
+ _end_of_message_
264
+ msg.gsub!(/^ {6}/, "")
265
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
266
+ req.parse(StringIO.new(msg))
267
+ assert_equal("server.example.com", req.server_name)
268
+ assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
269
+ assert_equal("forward.example.com", req.host)
270
+ assert_equal(80, req.port)
271
+ assert_equal("123.123.123.123", req.remote_ip)
272
+ assert(!req.ssl?)
273
+
274
+ msg = <<-_end_of_message_
275
+ GET /foo HTTP/1.1
276
+ Host: localhost:10080
277
+ User-Agent: w3m/0.5.2
278
+ X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
279
+ X-Forwarded-Host: forward.example.com:8080
280
+ X-Forwarded-Server: server.example.com
281
+ Connection: Keep-Alive
282
+
283
+ _end_of_message_
284
+ msg.gsub!(/^ {6}/, "")
285
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
286
+ req.parse(StringIO.new(msg))
287
+ assert_equal("server.example.com", req.server_name)
288
+ assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
289
+ assert_equal("forward.example.com", req.host)
290
+ assert_equal(8080, req.port)
291
+ assert_equal("123.123.123.123", req.remote_ip)
292
+ assert(!req.ssl?)
293
+
294
+ msg = <<-_end_of_message_
295
+ GET /foo HTTP/1.1
296
+ Host: localhost:10080
297
+ Client-IP: 234.234.234.234
298
+ X-Forwarded-Proto: https
299
+ X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
300
+ X-Forwarded-Host: forward.example.com
301
+ X-Forwarded-Server: server.example.com
302
+ X-Requested-With: XMLHttpRequest
303
+ Connection: Keep-Alive
304
+
305
+ _end_of_message_
306
+ msg.gsub!(/^ {6}/, "")
307
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
308
+ req.parse(StringIO.new(msg))
309
+ assert_equal("server.example.com", req.server_name)
310
+ assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
311
+ assert_equal("forward.example.com", req.host)
312
+ assert_equal(443, req.port)
313
+ assert_equal("234.234.234.234", req.remote_ip)
314
+ assert(req.ssl?)
315
+
316
+ msg = <<-_end_of_message_
317
+ GET /foo HTTP/1.1
318
+ Host: localhost:10080
319
+ Client-IP: 234.234.234.234
320
+ X-Forwarded-Proto: https
321
+ X-Forwarded-For: 192.168.1.10
322
+ X-Forwarded-Host: forward1.example.com:1234, forward2.example.com:5678
323
+ X-Forwarded-Server: server1.example.com, server2.example.com
324
+ X-Requested-With: XMLHttpRequest
325
+ Connection: Keep-Alive
326
+
327
+ _end_of_message_
328
+ msg.gsub!(/^ {6}/, "")
329
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
330
+ req.parse(StringIO.new(msg))
331
+ assert_equal("server1.example.com", req.server_name)
332
+ assert_equal("https://forward1.example.com:1234/foo", req.request_uri.to_s)
333
+ assert_equal("forward1.example.com", req.host)
334
+ assert_equal(1234, req.port)
335
+ assert_equal("234.234.234.234", req.remote_ip)
336
+ assert(req.ssl?)
337
+ end
338
+
339
+ def test_continue_sent
340
+ msg = <<-_end_of_message_
341
+ POST /path HTTP/1.1
342
+ Expect: 100-continue
343
+
344
+ _end_of_message_
345
+ msg.gsub!(/^ {6}/, "")
346
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
347
+ req.parse(StringIO.new(msg))
348
+ assert req['expect']
349
+ l = msg.size
350
+ req.continue
351
+ assert_not_equal l, msg.size
352
+ assert_match /HTTP\/1.1 100 continue\r\n\r\n\z/, msg
353
+ assert !req['expect']
354
+ end
355
+
356
+ def test_continue_not_sent
357
+ msg = <<-_end_of_message_
358
+ POST /path HTTP/1.1
359
+
360
+ _end_of_message_
361
+ msg.gsub!(/^ {6}/, "")
362
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
363
+ req.parse(StringIO.new(msg))
364
+ assert !req['expect']
365
+ l = msg.size
366
+ req.continue
367
+ assert_equal l, msg.size
368
+ end
369
+
370
+ def test_bad_messages
371
+ param = "foo=1;foo=2;foo=3;bar=x"
372
+ msg = <<-_end_of_message_
373
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
374
+ Host: test.ruby-lang.org:8080
375
+ Content-Type: application/x-www-form-urlencoded
376
+
377
+ #{param}
378
+ _end_of_message_
379
+ assert_raise(WEBrick::HTTPStatus::LengthRequired){
380
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
381
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
382
+ req.body
383
+ }
384
+
385
+ msg = <<-_end_of_message_
386
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
387
+ Host: test.ruby-lang.org:8080
388
+ Content-Length: 100000
389
+
390
+ body is too short.
391
+ _end_of_message_
392
+ assert_raise(WEBrick::HTTPStatus::BadRequest){
393
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
394
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
395
+ req.body
396
+ }
397
+
398
+ msg = <<-_end_of_message_
399
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
400
+ Host: test.ruby-lang.org:8080
401
+ Transfer-Encoding: foobar
402
+
403
+ body is too short.
404
+ _end_of_message_
405
+ assert_raise(WEBrick::HTTPStatus::NotImplemented){
406
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
407
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
408
+ req.body
409
+ }
410
+ end
411
+ end