webrick 1.3.1 → 1.4.3

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/lib/webrick.rb +6 -6
  3. data/lib/webrick/accesslog.rb +9 -1
  4. data/lib/webrick/cgi.rb +58 -5
  5. data/lib/webrick/compat.rb +2 -1
  6. data/lib/webrick/config.rb +47 -10
  7. data/lib/webrick/cookie.rb +69 -7
  8. data/lib/webrick/htmlutils.rb +4 -2
  9. data/lib/webrick/httpauth.rb +6 -5
  10. data/lib/webrick/httpauth/authenticator.rb +13 -8
  11. data/lib/webrick/httpauth/basicauth.rb +16 -8
  12. data/lib/webrick/httpauth/digestauth.rb +35 -32
  13. data/lib/webrick/httpauth/htdigest.rb +12 -8
  14. data/lib/webrick/httpauth/htgroup.rb +10 -6
  15. data/lib/webrick/httpauth/htpasswd.rb +46 -9
  16. data/lib/webrick/httpauth/userdb.rb +1 -0
  17. data/lib/webrick/httpproxy.rb +93 -48
  18. data/lib/webrick/httprequest.rb +192 -27
  19. data/lib/webrick/httpresponse.rb +182 -62
  20. data/lib/webrick/https.rb +90 -2
  21. data/lib/webrick/httpserver.rb +45 -15
  22. data/lib/webrick/httpservlet.rb +6 -5
  23. data/lib/webrick/httpservlet/abstract.rb +5 -6
  24. data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
  25. data/lib/webrick/httpservlet/cgihandler.rb +22 -10
  26. data/lib/webrick/httpservlet/erbhandler.rb +4 -3
  27. data/lib/webrick/httpservlet/filehandler.rb +136 -65
  28. data/lib/webrick/httpservlet/prochandler.rb +15 -1
  29. data/lib/webrick/httpstatus.rb +24 -14
  30. data/lib/webrick/httputils.rb +132 -13
  31. data/lib/webrick/httpversion.rb +28 -1
  32. data/lib/webrick/log.rb +25 -5
  33. data/lib/webrick/server.rb +234 -74
  34. data/lib/webrick/ssl.rb +100 -12
  35. data/lib/webrick/utils.rb +98 -69
  36. data/lib/webrick/version.rb +6 -1
  37. metadata +66 -72
  38. data/README.txt +0 -21
  39. data/sample/webrick/demo-app.rb +0 -66
  40. data/sample/webrick/demo-multipart.cgi +0 -12
  41. data/sample/webrick/demo-servlet.rb +0 -6
  42. data/sample/webrick/demo-urlencoded.cgi +0 -12
  43. data/sample/webrick/hello.cgi +0 -11
  44. data/sample/webrick/hello.rb +0 -8
  45. data/sample/webrick/httpd.rb +0 -23
  46. data/sample/webrick/httpproxy.rb +0 -25
  47. data/sample/webrick/httpsd.rb +0 -33
  48. data/test/openssl/utils.rb +0 -313
  49. data/test/ruby/envutil.rb +0 -208
  50. data/test/webrick/test_cgi.rb +0 -134
  51. data/test/webrick/test_cookie.rb +0 -131
  52. data/test/webrick/test_filehandler.rb +0 -285
  53. data/test/webrick/test_httpauth.rb +0 -167
  54. data/test/webrick/test_httpproxy.rb +0 -282
  55. data/test/webrick/test_httprequest.rb +0 -411
  56. data/test/webrick/test_httpresponse.rb +0 -49
  57. data/test/webrick/test_httpserver.rb +0 -305
  58. data/test/webrick/test_httputils.rb +0 -96
  59. data/test/webrick/test_httpversion.rb +0 -40
  60. data/test/webrick/test_server.rb +0 -67
  61. data/test/webrick/test_utils.rb +0 -64
  62. data/test/webrick/utils.rb +0 -58
  63. data/test/webrick/webrick.cgi +0 -36
  64. data/test/webrick/webrick_long_filename.cgi +0 -36
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  #--
2
3
  # httpauth/userdb.rb -- UserDB mix-in module.
3
4
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  #
2
3
  # httpproxy.rb -- HTTPProxy Class
3
4
  #
@@ -9,22 +10,21 @@
9
10
  # $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
10
11
  # $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
11
12
 
12
- require "webrick/httpserver"
13
+ require_relative "httpserver"
13
14
  require "net/http"
14
15
 
15
- Net::HTTP::version_1_2 if RUBY_VERSION < "1.7"
16
-
17
16
  module WEBrick
18
- NullReader = Object.new
19
- class << NullReader
17
+
18
+ NullReader = Object.new # :nodoc:
19
+ class << NullReader # :nodoc:
20
20
  def read(*args)
21
21
  nil
22
22
  end
23
23
  alias gets read
24
24
  end
25
25
 
26
- FakeProxyURI = Object.new
27
- class << FakeProxyURI
26
+ FakeProxyURI = Object.new # :nodoc:
27
+ class << FakeProxyURI # :nodoc:
28
28
  def method_missing(meth, *args)
29
29
  if %w(scheme host port path query userinfo).member?(meth.to_s)
30
30
  return nil
@@ -33,8 +33,38 @@ module WEBrick
33
33
  end
34
34
  end
35
35
 
36
+ # :startdoc:
37
+
36
38
  ##
37
39
  # An HTTP Proxy server which proxies GET, HEAD and POST requests.
40
+ #
41
+ # To create a simple proxy server:
42
+ #
43
+ # require 'webrick'
44
+ # require 'webrick/httpproxy'
45
+ #
46
+ # proxy = WEBrick::HTTPProxyServer.new Port: 8000
47
+ #
48
+ # trap 'INT' do proxy.shutdown end
49
+ # trap 'TERM' do proxy.shutdown end
50
+ #
51
+ # proxy.start
52
+ #
53
+ # See ::new for proxy-specific configuration items.
54
+ #
55
+ # == Modifying proxied responses
56
+ #
57
+ # To modify content the proxy server returns use the +:ProxyContentHandler+
58
+ # option:
59
+ #
60
+ # handler = proc do |req, res|
61
+ # if res['content-type'] == 'text/plain' then
62
+ # res.body << "\nThis content was proxied!\n"
63
+ # end
64
+ # end
65
+ #
66
+ # proxy =
67
+ # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler
38
68
 
39
69
  class HTTPProxyServer < HTTPServer
40
70
 
@@ -46,7 +76,7 @@ module WEBrick
46
76
  # request
47
77
  # :ProxyVia:: Appended to the via header
48
78
  # :ProxyURI:: The proxy server's URI
49
- # :ProxyContentHandler:: Called with a request and resopnse and allows
79
+ # :ProxyContentHandler:: Called with a request and response and allows
50
80
  # modification of the response
51
81
  # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60
52
82
  # seconds for read operations
@@ -57,6 +87,7 @@ module WEBrick
57
87
  @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
58
88
  end
59
89
 
90
+ # :stopdoc:
60
91
  def service(req, res)
61
92
  if req.request_method == "CONNECT"
62
93
  do_CONNECT(req, res)
@@ -112,7 +143,7 @@ module WEBrick
112
143
  if proxy = proxy_uri(req, res)
113
144
  proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
114
145
  if proxy.userinfo
115
- credentials = "Basic " + [proxy.userinfo].pack("m").delete("\n")
146
+ credentials = "Basic " + [proxy.userinfo].pack("m0")
116
147
  end
117
148
  host, port = proxy.host, proxy.port
118
149
  end
@@ -126,12 +157,12 @@ module WEBrick
126
157
  os << proxy_request_line << CRLF
127
158
  @logger.debug("CONNECT: > #{proxy_request_line}")
128
159
  if credentials
129
- @logger.debug("CONNECT: sending a credentials")
160
+ @logger.debug("CONNECT: sending credentials")
130
161
  os << "Proxy-Authorization: " << credentials << CRLF
131
162
  end
132
163
  os << CRLF
133
164
  proxy_status_line = os.gets(LF)
134
- @logger.debug("CONNECT: read a Status-Line form the upstream server")
165
+ @logger.debug("CONNECT: read Status-Line from the upstream server")
135
166
  @logger.debug("CONNECT: < #{proxy_status_line}")
136
167
  if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
137
168
  while line = os.gets(LF)
@@ -154,7 +185,7 @@ module WEBrick
154
185
  res.send_response(ua)
155
186
  access_log(@config, req, res)
156
187
 
157
- # Should clear request-line not to send the sesponse twice.
188
+ # Should clear request-line not to send the response twice.
158
189
  # see: HTTPServer#run
159
190
  req.parse(NullReader) rescue nil
160
191
  end
@@ -162,16 +193,16 @@ module WEBrick
162
193
  begin
163
194
  while fds = IO::select([ua, os])
164
195
  if fds[0].member?(ua)
165
- buf = ua.sysread(1024);
196
+ buf = ua.readpartial(1024);
166
197
  @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
167
- os.syswrite(buf)
198
+ os.write(buf)
168
199
  elsif fds[0].member?(os)
169
- buf = os.sysread(1024);
200
+ buf = os.readpartial(1024);
170
201
  @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
171
- ua.syswrite(buf)
202
+ ua.write(buf)
172
203
  end
173
204
  end
174
- rescue => ex
205
+ rescue
175
206
  os.close
176
207
  @logger.debug("CONNECT #{host}:#{port}: closed")
177
208
  end
@@ -180,21 +211,15 @@ module WEBrick
180
211
  end
181
212
 
182
213
  def do_GET(req, res)
183
- perform_proxy_request(req, res) do |http, path, header|
184
- http.get(path, header)
185
- end
214
+ perform_proxy_request(req, res, Net::HTTP::Get)
186
215
  end
187
216
 
188
217
  def do_HEAD(req, res)
189
- perform_proxy_request(req, res) do |http, path, header|
190
- http.head(path, header)
191
- end
218
+ perform_proxy_request(req, res, Net::HTTP::Head)
192
219
  end
193
220
 
194
221
  def do_POST(req, res)
195
- perform_proxy_request(req, res) do |http, path, header|
196
- http.post(path, req.body || "", header)
197
- end
222
+ perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
198
223
  end
199
224
 
200
225
  def do_OPTIONS(req, res)
@@ -263,43 +288,63 @@ module WEBrick
263
288
  if upstream = proxy_uri(req, res)
264
289
  if upstream.userinfo
265
290
  header['proxy-authorization'] =
266
- "Basic " + [upstream.userinfo].pack("m").delete("\n")
291
+ "Basic " + [upstream.userinfo].pack("m0")
267
292
  end
268
293
  return upstream
269
294
  end
270
295
  return FakeProxyURI
271
296
  end
272
297
 
273
- def perform_proxy_request(req, res)
298
+ def perform_proxy_request(req, res, req_class, body_stream = nil)
274
299
  uri = req.request_uri
275
300
  path = uri.path.dup
276
301
  path << "?" << uri.query if uri.query
277
302
  header = setup_proxy_header(req, res)
278
303
  upstream = setup_upstream_proxy_authentication(req, res, header)
279
- response = nil
280
304
 
305
+ body_tmp = []
281
306
  http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
282
- http.start do
283
- if @config[:ProxyTimeout]
284
- ################################## these issues are
285
- http.open_timeout = 30 # secs # necessary (maybe bacause
286
- http.read_timeout = 60 # secs # Ruby's bug, but why?)
287
- ##################################
307
+ req_fib = Fiber.new do
308
+ http.start do
309
+ if @config[:ProxyTimeout]
310
+ ################################## these issues are
311
+ http.open_timeout = 30 # secs # necessary (maybe because
312
+ http.read_timeout = 60 # secs # Ruby's bug, but why?)
313
+ ##################################
314
+ end
315
+ if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i
316
+ header['Transfer-Encoding'] = 'chunked'
317
+ end
318
+ http_req = req_class.new(path, header)
319
+ http_req.body_stream = body_stream if body_stream
320
+ http.request(http_req) do |response|
321
+ # Persistent connection requirements are mysterious for me.
322
+ # So I will close the connection in every response.
323
+ res['proxy-connection'] = "close"
324
+ res['connection'] = "close"
325
+
326
+ # stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
327
+ res.status = response.code.to_i
328
+ res.chunked = response.chunked?
329
+ choose_header(response, res)
330
+ set_cookie(response, res)
331
+ set_via(res)
332
+ response.read_body do |buf|
333
+ body_tmp << buf
334
+ Fiber.yield # wait for res.body Proc#call
335
+ end
336
+ end # http.request
337
+ end
338
+ end
339
+ req_fib.resume # read HTTP response headers and first chunk of the body
340
+ res.body = ->(socket) do
341
+ while buf = body_tmp.shift
342
+ socket.write(buf)
343
+ buf.clear
344
+ req_fib.resume # continue response.read_body
288
345
  end
289
- response = yield(http, path, header)
290
346
  end
291
-
292
- # Persistent connection requirements are mysterious for me.
293
- # So I will close the connection in every response.
294
- res['proxy-connection'] = "close"
295
- res['connection'] = "close"
296
-
297
- # Convert Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
298
- res.status = response.code.to_i
299
- choose_header(response, res)
300
- set_cookie(response, res)
301
- set_via(res)
302
- res.body = response.body
303
347
  end
348
+ # :stopdoc:
304
349
  end
305
350
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  #
2
3
  # httprequest.rb -- HTTPRequest Class
3
4
  #
@@ -9,39 +10,145 @@
9
10
  # $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
10
11
 
11
12
  require 'uri'
12
- require 'webrick/httpversion'
13
- require 'webrick/httpstatus'
14
- require 'webrick/httputils'
15
- require 'webrick/cookie'
13
+ require_relative 'httpversion'
14
+ require_relative 'httpstatus'
15
+ require_relative 'httputils'
16
+ require_relative 'cookie'
16
17
 
17
18
  module WEBrick
18
19
 
19
20
  ##
20
- # An HTTP request.
21
+ # An HTTP request. This is consumed by service and do_* methods in
22
+ # WEBrick servlets
23
+
21
24
  class HTTPRequest
22
25
 
23
- BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ]
26
+ BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
24
27
 
25
28
  # :section: Request line
29
+
30
+ ##
31
+ # The complete request line such as:
32
+ #
33
+ # GET / HTTP/1.1
34
+
26
35
  attr_reader :request_line
27
- attr_reader :request_method, :unparsed_uri, :http_version
36
+
37
+ ##
38
+ # The request method, GET, POST, PUT, etc.
39
+
40
+ attr_reader :request_method
41
+
42
+ ##
43
+ # The unparsed URI of the request
44
+
45
+ attr_reader :unparsed_uri
46
+
47
+ ##
48
+ # The HTTP version of the request
49
+
50
+ attr_reader :http_version
28
51
 
29
52
  # :section: Request-URI
30
- attr_reader :request_uri, :path
31
- attr_accessor :script_name, :path_info, :query_string
53
+
54
+ ##
55
+ # The parsed URI of the request
56
+
57
+ attr_reader :request_uri
58
+
59
+ ##
60
+ # The request path
61
+
62
+ attr_reader :path
63
+
64
+ ##
65
+ # The script name (CGI variable)
66
+
67
+ attr_accessor :script_name
68
+
69
+ ##
70
+ # The path info (CGI variable)
71
+
72
+ attr_accessor :path_info
73
+
74
+ ##
75
+ # The query from the URI of the request
76
+
77
+ attr_accessor :query_string
32
78
 
33
79
  # :section: Header and entity body
34
- attr_reader :raw_header, :header, :cookies
35
- attr_reader :accept, :accept_charset
36
- attr_reader :accept_encoding, :accept_language
80
+
81
+ ##
82
+ # The raw header of the request
83
+
84
+ attr_reader :raw_header
85
+
86
+ ##
87
+ # The parsed header of the request
88
+
89
+ attr_reader :header
90
+
91
+ ##
92
+ # The parsed request cookies
93
+
94
+ attr_reader :cookies
95
+
96
+ ##
97
+ # The Accept header value
98
+
99
+ attr_reader :accept
100
+
101
+ ##
102
+ # The Accept-Charset header value
103
+
104
+ attr_reader :accept_charset
105
+
106
+ ##
107
+ # The Accept-Encoding header value
108
+
109
+ attr_reader :accept_encoding
110
+
111
+ ##
112
+ # The Accept-Language header value
113
+
114
+ attr_reader :accept_language
37
115
 
38
116
  # :section:
117
+
118
+ ##
119
+ # The remote user (CGI variable)
120
+
39
121
  attr_accessor :user
40
- attr_reader :addr, :peeraddr
122
+
123
+ ##
124
+ # The socket address of the server
125
+
126
+ attr_reader :addr
127
+
128
+ ##
129
+ # The socket address of the client
130
+
131
+ attr_reader :peeraddr
132
+
133
+ ##
134
+ # Hash of request attributes
135
+
41
136
  attr_reader :attributes
137
+
138
+ ##
139
+ # Is this a keep-alive connection?
140
+
42
141
  attr_reader :keep_alive
142
+
143
+ ##
144
+ # The local time this request was received
145
+
43
146
  attr_reader :request_time
44
147
 
148
+ ##
149
+ # Creates a new HTTP request. WEBrick::Config::HTTP is the default
150
+ # configuration.
151
+
45
152
  def initialize(config)
46
153
  @config = config
47
154
  @buffer_size = @config[:InputBufferSize]
@@ -78,6 +185,10 @@ module WEBrick
78
185
  @forwarded_server = @forwarded_for = nil
79
186
  end
80
187
 
188
+ ##
189
+ # Parses a request from +socket+. This is called internally by
190
+ # WEBrick::HTTPServer.
191
+
81
192
  def parse(socket=nil)
82
193
  @socket = socket
83
194
  begin
@@ -126,21 +237,52 @@ module WEBrick
126
237
  end
127
238
  end
128
239
 
240
+ ##
129
241
  # Generate HTTP/1.1 100 continue response if the client expects it,
130
242
  # otherwise does nothing.
131
- def continue
243
+
244
+ def continue # :nodoc:
132
245
  if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
133
246
  @socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
134
247
  @header.delete('expect')
135
248
  end
136
249
  end
137
250
 
138
- def body(&block)
251
+ ##
252
+ # Returns the request body.
253
+
254
+ def body(&block) # :yields: body_chunk
139
255
  block ||= Proc.new{|chunk| @body << chunk }
140
256
  read_body(@socket, block)
141
257
  @body.empty? ? nil : @body
142
258
  end
143
259
 
260
+ ##
261
+ # Prepares the HTTPRequest object for use as the
262
+ # source for IO.copy_stream
263
+
264
+ def body_reader
265
+ @body_tmp = []
266
+ @body_rd = Fiber.new do
267
+ body do |buf|
268
+ @body_tmp << buf
269
+ Fiber.yield
270
+ end
271
+ end
272
+ @body_rd.resume # grab the first chunk and yield
273
+ self
274
+ end
275
+
276
+ # for IO.copy_stream. Note: we may return a larger string than +size+
277
+ # here; but IO.copy_stream does not care.
278
+ def readpartial(size, buf = ''.b) # :nodoc
279
+ res = @body_tmp.shift or raise EOFError, 'end of file reached'
280
+ buf.replace(res)
281
+ res.clear
282
+ @body_rd.resume # get more chunks
283
+ buf
284
+ end
285
+
144
286
  ##
145
287
  # Request query as a Hash
146
288
 
@@ -237,11 +379,14 @@ module WEBrick
237
379
  ret
238
380
  end
239
381
 
240
- def fixup()
382
+ ##
383
+ # Consumes any remaining body and updates keep-alive status
384
+
385
+ def fixup() # :nodoc:
241
386
  begin
242
387
  body{|chunk| } # read remaining body
243
388
  rescue HTTPStatus::Error => ex
244
- @logger.error("HTTPRequest#fixup: #{ex.class} occured.")
389
+ @logger.error("HTTPRequest#fixup: #{ex.class} occurred.")
245
390
  @keep_alive = false
246
391
  rescue => ex
247
392
  @logger.error(ex)
@@ -251,7 +396,8 @@ module WEBrick
251
396
 
252
397
  # This method provides the metavariables defined by the revision 3
253
398
  # of "The WWW Common Gateway Interface Version 1.1"
254
- # http://Web.Golux.Com/coar/cgi/
399
+ # To browse the current document of CGI Version 1.1, see below:
400
+ # http://tools.ietf.org/html/rfc3875
255
401
 
256
402
  def meta_vars
257
403
  meta = Hash.new
@@ -290,15 +436,23 @@ module WEBrick
290
436
 
291
437
  private
292
438
 
439
+ # :stopdoc:
440
+
293
441
  MAX_URI_LENGTH = 2083 # :nodoc:
294
442
 
443
+ # same as Mongrel, Thin and Puma
444
+ MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
445
+
295
446
  def read_request_line(socket)
296
447
  @request_line = read_line(socket, MAX_URI_LENGTH) if socket
297
- if @request_line.bytesize >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
448
+ raise HTTPStatus::EOFError unless @request_line
449
+
450
+ @request_bytes = @request_line.bytesize
451
+ if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
298
452
  raise HTTPStatus::RequestURITooLarge
299
453
  end
454
+
300
455
  @request_time = Time.now
301
- raise HTTPStatus::EOFError unless @request_line
302
456
  if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
303
457
  @request_method = $1
304
458
  @unparsed_uri = $2
@@ -313,6 +467,9 @@ module WEBrick
313
467
  if socket
314
468
  while line = read_line(socket)
315
469
  break if /\A(#{CRLF}|#{LF})\z/om =~ line
470
+ if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
471
+ raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
472
+ end
316
473
  @raw_header << line
317
474
  end
318
475
  end
@@ -380,12 +537,16 @@ module WEBrick
380
537
  def read_chunked(socket, block)
381
538
  chunk_size, = read_chunk_size(socket)
382
539
  while chunk_size > 0
383
- data = read_data(socket, chunk_size) # read chunk-data
384
- if data.nil? || data.bytesize != chunk_size
385
- raise BadRequest, "bad chunk data size."
386
- end
540
+ begin
541
+ sz = [ chunk_size, @buffer_size ].min
542
+ data = read_data(socket, sz) # read chunk-data
543
+ if data.nil? || data.bytesize != sz
544
+ raise HTTPStatus::BadRequest, "bad chunk data size."
545
+ end
546
+ block.call(data)
547
+ end while (chunk_size -= sz) > 0
548
+
387
549
  read_line(socket) # skip CRLF
388
- block.call(data)
389
550
  chunk_size, = read_chunk_size(socket)
390
551
  end
391
552
  read_header(socket) # trailer + CRLF
@@ -400,7 +561,7 @@ module WEBrick
400
561
  }
401
562
  rescue Errno::ECONNRESET
402
563
  return nil
403
- rescue TimeoutError
564
+ rescue Timeout::Error
404
565
  raise HTTPStatus::RequestTimeout
405
566
  end
406
567
  end
@@ -445,7 +606,9 @@ module WEBrick
445
606
  if @forwarded_server = self["x-forwarded-server"]
446
607
  @forwarded_server = @forwarded_server.split(",", 2).first
447
608
  end
448
- @forwarded_proto = self["x-forwarded-proto"]
609
+ if @forwarded_proto = self["x-forwarded-proto"]
610
+ @forwarded_proto = @forwarded_proto.split(",", 2).first
611
+ end
449
612
  if host_port = self["x-forwarded-host"]
450
613
  host_port = host_port.split(",", 2).first
451
614
  @forwarded_host, tmp = host_port.split(":", 2)
@@ -457,5 +620,7 @@ module WEBrick
457
620
  @forwarded_for = addrs.first
458
621
  end
459
622
  end
623
+
624
+ # :startdoc:
460
625
  end
461
626
  end