webrick 1.4.1 → 1.6.1
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.
Potentially problematic release.
This version of webrick might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/webrick.rb +1 -1
- data/lib/webrick/accesslog.rb +3 -5
- data/lib/webrick/cgi.rb +7 -3
- data/lib/webrick/config.rb +5 -5
- data/lib/webrick/cookie.rb +1 -1
- data/lib/webrick/httpauth.rb +5 -5
- data/lib/webrick/httpauth/basicauth.rb +13 -5
- data/lib/webrick/httpauth/digestauth.rb +10 -23
- data/lib/webrick/httpauth/htdigest.rb +4 -4
- data/lib/webrick/httpauth/htgroup.rb +9 -6
- data/lib/webrick/httpauth/htpasswd.rb +39 -6
- data/lib/webrick/httpproxy.rb +44 -32
- data/lib/webrick/httprequest.rb +59 -15
- data/lib/webrick/httpresponse.rb +111 -52
- data/lib/webrick/https.rb +2 -2
- data/lib/webrick/httpserver.rb +23 -9
- data/lib/webrick/httpservlet.rb +5 -5
- data/lib/webrick/httpservlet/abstract.rb +3 -3
- data/lib/webrick/httpservlet/cgi_runner.rb +2 -2
- data/lib/webrick/httpservlet/cgihandler.rb +10 -6
- data/lib/webrick/httpservlet/erbhandler.rb +2 -2
- data/lib/webrick/httpservlet/filehandler.rb +49 -30
- data/lib/webrick/httpservlet/prochandler.rb +1 -1
- data/lib/webrick/httpstatus.rb +1 -1
- data/lib/webrick/httputils.rb +4 -4
- data/lib/webrick/log.rb +1 -1
- data/lib/webrick/server.rb +2 -2
- data/lib/webrick/ssl.rb +2 -2
- data/lib/webrick/version.rb +1 -1
- data/webrick.gemspec +76 -0
- metadata +16 -10
data/lib/webrick/httpproxy.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
|
11
11
|
# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
|
12
12
|
|
13
|
-
|
13
|
+
require_relative "httpserver"
|
14
14
|
require "net/http"
|
15
15
|
|
16
16
|
module WEBrick
|
@@ -211,21 +211,15 @@ module WEBrick
|
|
211
211
|
end
|
212
212
|
|
213
213
|
def do_GET(req, res)
|
214
|
-
perform_proxy_request(req, res
|
215
|
-
http.get(path, header)
|
216
|
-
end
|
214
|
+
perform_proxy_request(req, res, Net::HTTP::Get)
|
217
215
|
end
|
218
216
|
|
219
217
|
def do_HEAD(req, res)
|
220
|
-
perform_proxy_request(req, res
|
221
|
-
http.head(path, header)
|
222
|
-
end
|
218
|
+
perform_proxy_request(req, res, Net::HTTP::Head)
|
223
219
|
end
|
224
220
|
|
225
221
|
def do_POST(req, res)
|
226
|
-
perform_proxy_request(req, res
|
227
|
-
http.post(path, req.body || "", header)
|
228
|
-
end
|
222
|
+
perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
|
229
223
|
end
|
230
224
|
|
231
225
|
def do_OPTIONS(req, res)
|
@@ -301,38 +295,56 @@ module WEBrick
|
|
301
295
|
return FakeProxyURI
|
302
296
|
end
|
303
297
|
|
304
|
-
def perform_proxy_request(req, res)
|
298
|
+
def perform_proxy_request(req, res, req_class, body_stream = nil)
|
305
299
|
uri = req.request_uri
|
306
300
|
path = uri.path.dup
|
307
301
|
path << "?" << uri.query if uri.query
|
308
302
|
header = setup_proxy_header(req, res)
|
309
303
|
upstream = setup_upstream_proxy_authentication(req, res, header)
|
310
|
-
response = nil
|
311
304
|
|
305
|
+
body_tmp = []
|
312
306
|
http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
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
|
319
345
|
end
|
320
|
-
response = yield(http, path, header)
|
321
346
|
end
|
322
|
-
|
323
|
-
# Persistent connection requirements are mysterious for me.
|
324
|
-
# So I will close the connection in every response.
|
325
|
-
res['proxy-connection'] = "close"
|
326
|
-
res['connection'] = "close"
|
327
|
-
|
328
|
-
# Convert Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
|
329
|
-
res.status = response.code.to_i
|
330
|
-
choose_header(response, res)
|
331
|
-
set_cookie(response, res)
|
332
|
-
set_via(res)
|
333
|
-
res.body = response.body
|
334
347
|
end
|
335
|
-
|
336
348
|
# :stopdoc:
|
337
349
|
end
|
338
350
|
end
|
data/lib/webrick/httprequest.rb
CHANGED
@@ -10,10 +10,10 @@
|
|
10
10
|
# $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
|
11
11
|
|
12
12
|
require 'uri'
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
require_relative 'httpversion'
|
14
|
+
require_relative 'httpstatus'
|
15
|
+
require_relative 'httputils'
|
16
|
+
require_relative 'cookie'
|
17
17
|
|
18
18
|
module WEBrick
|
19
19
|
|
@@ -226,9 +226,9 @@ module WEBrick
|
|
226
226
|
raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'."
|
227
227
|
end
|
228
228
|
|
229
|
-
if /
|
229
|
+
if /\Aclose\z/io =~ self["connection"]
|
230
230
|
@keep_alive = false
|
231
|
-
elsif
|
231
|
+
elsif /\Akeep-alive\z/io =~ self["connection"]
|
232
232
|
@keep_alive = true
|
233
233
|
elsif @http_version < "1.1"
|
234
234
|
@keep_alive = false
|
@@ -257,6 +257,32 @@ module WEBrick
|
|
257
257
|
@body.empty? ? nil : @body
|
258
258
|
end
|
259
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
|
+
|
260
286
|
##
|
261
287
|
# Request query as a Hash
|
262
288
|
|
@@ -414,13 +440,19 @@ module WEBrick
|
|
414
440
|
|
415
441
|
MAX_URI_LENGTH = 2083 # :nodoc:
|
416
442
|
|
443
|
+
# same as Mongrel, Thin and Puma
|
444
|
+
MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
|
445
|
+
|
417
446
|
def read_request_line(socket)
|
418
447
|
@request_line = read_line(socket, MAX_URI_LENGTH) if socket
|
419
|
-
|
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
|
420
452
|
raise HTTPStatus::RequestURITooLarge
|
421
453
|
end
|
454
|
+
|
422
455
|
@request_time = Time.now
|
423
|
-
raise HTTPStatus::EOFError unless @request_line
|
424
456
|
if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
|
425
457
|
@request_method = $1
|
426
458
|
@unparsed_uri = $2
|
@@ -435,6 +467,9 @@ module WEBrick
|
|
435
467
|
if socket
|
436
468
|
while line = read_line(socket)
|
437
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
|
438
473
|
@raw_header << line
|
439
474
|
end
|
440
475
|
end
|
@@ -468,7 +503,7 @@ module WEBrick
|
|
468
503
|
return unless socket
|
469
504
|
if tc = self['transfer-encoding']
|
470
505
|
case tc
|
471
|
-
when /
|
506
|
+
when /\Achunked\z/io then read_chunked(socket, block)
|
472
507
|
else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
|
473
508
|
end
|
474
509
|
elsif self['content-length'] || @remaining_size
|
@@ -502,12 +537,16 @@ module WEBrick
|
|
502
537
|
def read_chunked(socket, block)
|
503
538
|
chunk_size, = read_chunk_size(socket)
|
504
539
|
while chunk_size > 0
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
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
|
+
|
509
549
|
read_line(socket) # skip CRLF
|
510
|
-
block.call(data)
|
511
550
|
chunk_size, = read_chunk_size(socket)
|
512
551
|
end
|
513
552
|
read_header(socket) # trailer + CRLF
|
@@ -572,7 +611,12 @@ module WEBrick
|
|
572
611
|
end
|
573
612
|
if host_port = self["x-forwarded-host"]
|
574
613
|
host_port = host_port.split(",", 2).first
|
575
|
-
|
614
|
+
if host_port =~ /\A(\[[0-9a-fA-F:]+\])(?::(\d+))?\z/
|
615
|
+
@forwarded_host = $1
|
616
|
+
tmp = $2
|
617
|
+
else
|
618
|
+
@forwarded_host, tmp = host_port.split(":", 2)
|
619
|
+
end
|
576
620
|
@forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i
|
577
621
|
end
|
578
622
|
if addrs = self["x-forwarded-for"]
|
data/lib/webrick/httpresponse.rb
CHANGED
@@ -10,10 +10,11 @@
|
|
10
10
|
# $IPR: httpresponse.rb,v 1.45 2003/07/11 11:02:25 gotoyuzo Exp $
|
11
11
|
|
12
12
|
require 'time'
|
13
|
-
require '
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
require 'uri'
|
14
|
+
require_relative 'httpversion'
|
15
|
+
require_relative 'htmlutils'
|
16
|
+
require_relative 'httputils'
|
17
|
+
require_relative 'httpstatus'
|
17
18
|
|
18
19
|
module WEBrick
|
19
20
|
##
|
@@ -21,6 +22,8 @@ module WEBrick
|
|
21
22
|
# WEBrick HTTP Servlet.
|
22
23
|
|
23
24
|
class HTTPResponse
|
25
|
+
class InvalidHeader < StandardError
|
26
|
+
end
|
24
27
|
|
25
28
|
##
|
26
29
|
# HTTP Response version
|
@@ -48,8 +51,21 @@ module WEBrick
|
|
48
51
|
attr_accessor :reason_phrase
|
49
52
|
|
50
53
|
##
|
51
|
-
# Body may be
|
52
|
-
#
|
54
|
+
# Body may be:
|
55
|
+
# * a String;
|
56
|
+
# * an IO-like object that responds to +#read+ and +#readpartial+;
|
57
|
+
# * a Proc-like object that responds to +#call+.
|
58
|
+
#
|
59
|
+
# In the latter case, either #chunked= should be set to +true+,
|
60
|
+
# or <code>header['content-length']</code> explicitly provided.
|
61
|
+
# Example:
|
62
|
+
#
|
63
|
+
# server.mount_proc '/' do |req, res|
|
64
|
+
# res.chunked = true
|
65
|
+
# # or
|
66
|
+
# # res.header['content-length'] = 10
|
67
|
+
# res.body = proc { |out| out.write(Time.now.to_s) }
|
68
|
+
# end
|
53
69
|
|
54
70
|
attr_accessor :body
|
55
71
|
|
@@ -110,13 +126,14 @@ module WEBrick
|
|
110
126
|
@chunked = false
|
111
127
|
@filename = nil
|
112
128
|
@sent_size = 0
|
129
|
+
@bodytempfile = nil
|
113
130
|
end
|
114
131
|
|
115
132
|
##
|
116
133
|
# The response's HTTP status line
|
117
134
|
|
118
135
|
def status_line
|
119
|
-
"HTTP/#@http_version #@status #@reason_phrase
|
136
|
+
"HTTP/#@http_version #@status #@reason_phrase".rstrip << CRLF
|
120
137
|
end
|
121
138
|
|
122
139
|
##
|
@@ -138,6 +155,7 @@ module WEBrick
|
|
138
155
|
# Sets the response header +field+ to +value+
|
139
156
|
|
140
157
|
def []=(field, value)
|
158
|
+
@chunked = value.to_s.downcase == 'chunked' if field.downcase == 'transfer-encoding'
|
141
159
|
@header[field.downcase] = value.to_s
|
142
160
|
end
|
143
161
|
|
@@ -250,8 +268,11 @@ module WEBrick
|
|
250
268
|
elsif %r{^multipart/byteranges} =~ @header['content-type']
|
251
269
|
@header.delete('content-length')
|
252
270
|
elsif @header['content-length'].nil?
|
253
|
-
|
254
|
-
|
271
|
+
if @body.respond_to? :readpartial
|
272
|
+
elsif @body.respond_to? :call
|
273
|
+
make_body_tempfile
|
274
|
+
else
|
275
|
+
@header['content-length'] = (@body ? @body.bytesize : 0).to_s
|
255
276
|
end
|
256
277
|
end
|
257
278
|
|
@@ -274,11 +295,38 @@ module WEBrick
|
|
274
295
|
# Location is a single absoluteURI.
|
275
296
|
if location = @header['location']
|
276
297
|
if @request_uri
|
277
|
-
@header['location'] = @request_uri.merge(location)
|
298
|
+
@header['location'] = @request_uri.merge(location).to_s
|
278
299
|
end
|
279
300
|
end
|
280
301
|
end
|
281
302
|
|
303
|
+
def make_body_tempfile # :nodoc:
|
304
|
+
return if @bodytempfile
|
305
|
+
bodytempfile = Tempfile.create("webrick")
|
306
|
+
if @body.nil?
|
307
|
+
# nothing
|
308
|
+
elsif @body.respond_to? :readpartial
|
309
|
+
IO.copy_stream(@body, bodytempfile)
|
310
|
+
@body.close
|
311
|
+
elsif @body.respond_to? :call
|
312
|
+
@body.call(bodytempfile)
|
313
|
+
else
|
314
|
+
bodytempfile.write @body
|
315
|
+
end
|
316
|
+
bodytempfile.rewind
|
317
|
+
@body = @bodytempfile = bodytempfile
|
318
|
+
@header['content-length'] = bodytempfile.stat.size.to_s
|
319
|
+
end
|
320
|
+
|
321
|
+
def remove_body_tempfile # :nodoc:
|
322
|
+
if @bodytempfile
|
323
|
+
@bodytempfile.close
|
324
|
+
File.unlink @bodytempfile.path
|
325
|
+
@bodytempfile = nil
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
282
330
|
##
|
283
331
|
# Sends the headers on +socket+
|
284
332
|
|
@@ -287,14 +335,19 @@ module WEBrick
|
|
287
335
|
data = status_line()
|
288
336
|
@header.each{|key, value|
|
289
337
|
tmp = key.gsub(/\bwww|^te$|\b\w/){ $&.upcase }
|
290
|
-
data << "#{tmp}: #{value}" << CRLF
|
338
|
+
data << "#{tmp}: #{check_header(value)}" << CRLF
|
291
339
|
}
|
292
340
|
@cookies.each{|cookie|
|
293
|
-
data << "Set-Cookie: " << cookie.to_s << CRLF
|
341
|
+
data << "Set-Cookie: " << check_header(cookie.to_s) << CRLF
|
294
342
|
}
|
295
343
|
data << CRLF
|
296
|
-
|
344
|
+
socket.write(data)
|
297
345
|
end
|
346
|
+
rescue InvalidHeader => e
|
347
|
+
@header.clear
|
348
|
+
@cookies.clear
|
349
|
+
set_error e
|
350
|
+
retry
|
298
351
|
end
|
299
352
|
|
300
353
|
##
|
@@ -310,12 +363,6 @@ module WEBrick
|
|
310
363
|
end
|
311
364
|
end
|
312
365
|
|
313
|
-
def to_s # :nodoc:
|
314
|
-
ret = ""
|
315
|
-
send_response(ret)
|
316
|
-
ret
|
317
|
-
end
|
318
|
-
|
319
366
|
##
|
320
367
|
# Redirects to +url+ with a WEBrick::HTTPStatus::Redirect +status+.
|
321
368
|
#
|
@@ -324,8 +371,9 @@ module WEBrick
|
|
324
371
|
# res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect
|
325
372
|
|
326
373
|
def set_redirect(status, url)
|
374
|
+
url = URI(url).to_s
|
327
375
|
@body = "<HTML><A HREF=\"#{url}\">#{url}</A>.</HTML>\n"
|
328
|
-
@header['location'] = url
|
376
|
+
@header['location'] = url
|
329
377
|
raise status
|
330
378
|
end
|
331
379
|
|
@@ -359,6 +407,15 @@ module WEBrick
|
|
359
407
|
|
360
408
|
private
|
361
409
|
|
410
|
+
def check_header(header_value)
|
411
|
+
header_value = header_value.to_s
|
412
|
+
if /[\r\n]/ =~ header_value
|
413
|
+
raise InvalidHeader
|
414
|
+
else
|
415
|
+
header_value
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
362
419
|
# :stopdoc:
|
363
420
|
|
364
421
|
def error_body(backtrace, ex, host, port)
|
@@ -401,22 +458,34 @@ module WEBrick
|
|
401
458
|
@body.readpartial(@buffer_size, buf)
|
402
459
|
size = buf.bytesize
|
403
460
|
data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}"
|
404
|
-
|
461
|
+
socket.write(data)
|
405
462
|
data.clear
|
406
463
|
@sent_size += size
|
407
464
|
rescue EOFError
|
408
465
|
break
|
409
466
|
end while true
|
410
467
|
buf.clear
|
411
|
-
|
468
|
+
socket.write("0#{CRLF}#{CRLF}")
|
412
469
|
else
|
413
|
-
|
414
|
-
|
415
|
-
|
470
|
+
if %r{\Abytes (\d+)-(\d+)/\d+\z} =~ @header['content-range']
|
471
|
+
offset = $1.to_i
|
472
|
+
size = $2.to_i - offset + 1
|
473
|
+
else
|
474
|
+
offset = nil
|
475
|
+
size = @header['content-length']
|
476
|
+
size = size.to_i if size
|
477
|
+
end
|
478
|
+
begin
|
479
|
+
@sent_size = IO.copy_stream(@body, socket, size, offset)
|
480
|
+
rescue NotImplementedError
|
481
|
+
@body.seek(offset, IO::SEEK_SET)
|
482
|
+
@sent_size = IO.copy_stream(@body, socket, size)
|
483
|
+
end
|
416
484
|
end
|
417
485
|
ensure
|
418
486
|
@body.close
|
419
487
|
end
|
488
|
+
remove_body_tempfile
|
420
489
|
end
|
421
490
|
|
422
491
|
def send_body_string(socket)
|
@@ -429,13 +498,13 @@ module WEBrick
|
|
429
498
|
size = buf.bytesize
|
430
499
|
data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}"
|
431
500
|
buf.clear
|
432
|
-
|
501
|
+
socket.write(data)
|
433
502
|
@sent_size += size
|
434
503
|
end
|
435
|
-
|
504
|
+
socket.write("0#{CRLF}#{CRLF}")
|
436
505
|
else
|
437
506
|
if @body && @body.bytesize > 0
|
438
|
-
|
507
|
+
socket.write(@body)
|
439
508
|
@sent_size = @body.bytesize
|
440
509
|
end
|
441
510
|
end
|
@@ -446,10 +515,15 @@ module WEBrick
|
|
446
515
|
# do nothing
|
447
516
|
elsif chunked?
|
448
517
|
@body.call(ChunkedWrapper.new(socket, self))
|
449
|
-
|
518
|
+
socket.write("0#{CRLF}#{CRLF}")
|
450
519
|
else
|
451
520
|
size = @header['content-length'].to_i
|
452
|
-
@
|
521
|
+
if @bodytempfile
|
522
|
+
@bodytempfile.rewind
|
523
|
+
IO.copy_stream(@bodytempfile, socket)
|
524
|
+
else
|
525
|
+
@body.call(socket)
|
526
|
+
end
|
453
527
|
@sent_size = size
|
454
528
|
end
|
455
529
|
end
|
@@ -461,40 +535,25 @@ module WEBrick
|
|
461
535
|
end
|
462
536
|
|
463
537
|
def write(buf)
|
464
|
-
return if buf.empty?
|
538
|
+
return 0 if buf.empty?
|
465
539
|
socket = @socket
|
466
540
|
@resp.instance_eval {
|
467
541
|
size = buf.bytesize
|
468
542
|
data = "#{size.to_s(16)}#{CRLF}#{buf}#{CRLF}"
|
469
|
-
|
543
|
+
socket.write(data)
|
470
544
|
data.clear
|
471
545
|
@sent_size += size
|
546
|
+
size
|
472
547
|
}
|
473
548
|
end
|
474
|
-
alias :<< :write
|
475
|
-
end
|
476
|
-
|
477
|
-
def _send_file(output, input, offset, size)
|
478
|
-
while offset > 0
|
479
|
-
sz = @buffer_size < size ? @buffer_size : size
|
480
|
-
buf = input.read(sz)
|
481
|
-
offset -= buf.bytesize
|
482
|
-
end
|
483
549
|
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
end
|
488
|
-
else
|
489
|
-
while size > 0
|
490
|
-
sz = @buffer_size < size ? @buffer_size : size
|
491
|
-
buf = input.read(sz)
|
492
|
-
_write_data(output, buf)
|
493
|
-
size -= buf.bytesize
|
494
|
-
end
|
550
|
+
def <<(*buf)
|
551
|
+
write(buf)
|
552
|
+
self
|
495
553
|
end
|
496
554
|
end
|
497
555
|
|
556
|
+
# preserved for compatibility with some 3rd-party handlers
|
498
557
|
def _write_data(socket, data)
|
499
558
|
socket << data
|
500
559
|
end
|