webrick 1.4.0.beta1 → 1.4.4

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.

@@ -9,11 +9,11 @@
9
9
  #
10
10
  # $IPR: httpservlet.rb,v 1.21 2003/02/23 12:24:46 gotoyuzo Exp $
11
11
 
12
- require 'webrick/httpservlet/abstract'
13
- require 'webrick/httpservlet/filehandler'
14
- require 'webrick/httpservlet/cgihandler'
15
- require 'webrick/httpservlet/erbhandler'
16
- require 'webrick/httpservlet/prochandler'
12
+ require_relative 'httpservlet/abstract'
13
+ require_relative 'httpservlet/filehandler'
14
+ require_relative 'httpservlet/cgihandler'
15
+ require_relative 'httpservlet/erbhandler'
16
+ require_relative 'httpservlet/prochandler'
17
17
 
18
18
  module WEBrick
19
19
  module HTTPServlet
@@ -9,11 +9,9 @@
9
9
  #
10
10
  # $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $
11
11
 
12
- require 'thread'
13
-
14
- require 'webrick/htmlutils'
15
- require 'webrick/httputils'
16
- require 'webrick/httpstatus'
12
+ require_relative '../htmlutils'
13
+ require_relative '../httputils'
14
+ require_relative '../httpstatus'
17
15
 
18
16
  module WEBrick
19
17
  module HTTPServlet
@@ -23,11 +23,11 @@ STDIN.binmode
23
23
 
24
24
  len = sysread(STDIN, 8).to_i
25
25
  out = sysread(STDIN, len)
26
- STDOUT.reopen(open(out, "w"))
26
+ STDOUT.reopen(File.open(out, "w"))
27
27
 
28
28
  len = sysread(STDIN, 8).to_i
29
29
  err = sysread(STDIN, len)
30
- STDERR.reopen(open(err, "w"))
30
+ STDERR.reopen(File.open(err, "w"))
31
31
 
32
32
  len = sysread(STDIN, 8).to_i
33
33
  dump = sysread(STDIN, len)
@@ -11,8 +11,8 @@
11
11
 
12
12
  require 'rbconfig'
13
13
  require 'tempfile'
14
- require 'webrick/config'
15
- require 'webrick/httpservlet/abstract'
14
+ require_relative '../config'
15
+ require_relative 'abstract'
16
16
 
17
17
  module WEBrick
18
18
  module HTTPServlet
@@ -65,9 +65,7 @@ module WEBrick
65
65
  cgi_in.write("%8d" % dump.bytesize)
66
66
  cgi_in.write(dump)
67
67
 
68
- if req.body and req.body.bytesize > 0
69
- cgi_in.write(req.body)
70
- end
68
+ req.body { |chunk| cgi_in.write(chunk) }
71
69
  ensure
72
70
  cgi_in.close
73
71
  status = $?.exitstatus
@@ -9,7 +9,7 @@
9
9
  #
10
10
  # $IPR: erbhandler.rb,v 1.25 2003/02/24 19:25:31 gotoyuzo Exp $
11
11
 
12
- require 'webrick/httpservlet/abstract.rb'
12
+ require_relative 'abstract'
13
13
 
14
14
  require 'erb'
15
15
 
@@ -53,7 +53,7 @@ module WEBrick
53
53
  raise HTTPStatus::Forbidden, "ERBHandler cannot work."
54
54
  end
55
55
  begin
56
- data = open(@script_filename){|io| io.read }
56
+ data = File.open(@script_filename, &:read)
57
57
  res.body = evaluate(ERB.new(data), req, res)
58
58
  res['content-type'] ||=
59
59
  HTTPUtils::mime_type(@script_filename, @config[:MimeTypes])
@@ -9,12 +9,11 @@
9
9
  #
10
10
  # $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $
11
11
 
12
- require 'thread'
13
12
  require 'time'
14
13
 
15
- require 'webrick/htmlutils'
16
- require 'webrick/httputils'
17
- require 'webrick/httpstatus'
14
+ require_relative '../htmlutils'
15
+ require_relative '../httputils'
16
+ require_relative '../httpstatus'
18
17
 
19
18
  module WEBrick
20
19
  module HTTPServlet
@@ -56,9 +55,9 @@ module WEBrick
56
55
  else
57
56
  mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
58
57
  res['content-type'] = mtype
59
- res['content-length'] = st.size
58
+ res['content-length'] = st.size.to_s
60
59
  res['last-modified'] = mtime.httpdate
61
- res.body = open(@local_path, "rb")
60
+ res.body = File.open(@local_path, "rb")
62
61
  end
63
62
  end
64
63
 
@@ -87,47 +86,66 @@ module WEBrick
87
86
  return false
88
87
  end
89
88
 
89
+ # returns a lambda for webrick/httpresponse.rb send_body_proc
90
+ def multipart_body(body, parts, boundary, mtype, filesize)
91
+ lambda do |socket|
92
+ begin
93
+ begin
94
+ first = parts.shift
95
+ last = parts.shift
96
+ socket.write(
97
+ "--#{boundary}#{CRLF}" \
98
+ "Content-Type: #{mtype}#{CRLF}" \
99
+ "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
100
+ "#{CRLF}"
101
+ )
102
+
103
+ begin
104
+ IO.copy_stream(body, socket, last - first + 1, first)
105
+ rescue NotImplementedError
106
+ body.seek(first, IO::SEEK_SET)
107
+ IO.copy_stream(body, socket, last - first + 1)
108
+ end
109
+ socket.write(CRLF)
110
+ end while parts[0]
111
+ socket.write("--#{boundary}--#{CRLF}")
112
+ ensure
113
+ body.close
114
+ end
115
+ end
116
+ end
117
+
90
118
  def make_partial_content(req, res, filename, filesize)
91
119
  mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
92
120
  unless ranges = HTTPUtils::parse_range_header(req['range'])
93
121
  raise HTTPStatus::BadRequest,
94
122
  "Unrecognized range-spec: \"#{req['range']}\""
95
123
  end
96
- open(filename, "rb"){|io|
124
+ File.open(filename, "rb"){|io|
97
125
  if ranges.size > 1
98
126
  time = Time.now
99
127
  boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
100
- body = ''
101
- ranges.each{|range|
102
- first, last = prepare_range(range, filesize)
103
- next if first < 0
104
- io.pos = first
105
- content = io.read(last-first+1)
106
- body << "--" << boundary << CRLF
107
- body << "Content-Type: #{mtype}" << CRLF
108
- body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << CRLF
109
- body << CRLF
110
- body << content
111
- body << CRLF
128
+ parts = []
129
+ ranges.each {|range|
130
+ prange = prepare_range(range, filesize)
131
+ next if prange[0] < 0
132
+ parts.concat(prange)
112
133
  }
113
- raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
114
- body << "--" << boundary << "--" << CRLF
134
+ raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
115
135
  res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
116
- res.body = body
136
+ if req.http_version < '1.1'
137
+ res['connection'] = 'close'
138
+ else
139
+ res.chunked = true
140
+ end
141
+ res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
117
142
  elsif range = ranges[0]
118
143
  first, last = prepare_range(range, filesize)
119
144
  raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
120
- if last == filesize - 1
121
- content = io.dup
122
- content.pos = first
123
- else
124
- io.pos = first
125
- content = io.read(last-first+1)
126
- end
127
145
  res['content-type'] = mtype
128
146
  res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
129
- res['content-length'] = last - first + 1
130
- res.body = content
147
+ res['content-length'] = (last - first + 1).to_s
148
+ res.body = io.dup
131
149
  else
132
150
  raise HTTPStatus::BadRequest
133
151
  end
@@ -9,7 +9,7 @@
9
9
  #
10
10
  # $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $
11
11
 
12
- require 'webrick/httpservlet/abstract.rb'
12
+ require_relative 'abstract'
13
13
 
14
14
  module WEBrick
15
15
  module HTTPServlet
@@ -9,7 +9,7 @@
9
9
  #
10
10
  # $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $
11
11
 
12
- require 'webrick/accesslog'
12
+ require_relative 'accesslog'
13
13
 
14
14
  module WEBrick
15
15
 
@@ -23,10 +23,6 @@ module WEBrick
23
23
  ##
24
24
  # Root of the HTTP status class hierarchy
25
25
  class Status < StandardError
26
- def initialize(*args) # :nodoc:
27
- args[0] = AccessLog.escape(args[0]) unless args.empty?
28
- super(*args)
29
- end
30
26
  class << self
31
27
  attr_reader :code, :reason_phrase # :nodoc:
32
28
  end
@@ -69,6 +69,7 @@ module WEBrick
69
69
  "jpeg" => "image/jpeg",
70
70
  "jpg" => "image/jpeg",
71
71
  "js" => "application/javascript",
72
+ "json" => "application/json",
72
73
  "lha" => "application/octet-stream",
73
74
  "lzh" => "application/octet-stream",
74
75
  "mov" => "video/quicktime",
@@ -107,6 +108,8 @@ module WEBrick
107
108
  # Loads Apache-compatible mime.types in +file+.
108
109
 
109
110
  def load_mime_types(file)
111
+ # note: +file+ may be a "| command" for now; some people may
112
+ # rely on this, but currently we do not use this method by default.
110
113
  open(file){ |io|
111
114
  hash = Hash.new
112
115
  io.each{ |line|
@@ -51,7 +51,7 @@ module WEBrick
51
51
  @level = level || INFO
52
52
  case log_file
53
53
  when String
54
- @log = open(log_file, "a+")
54
+ @log = File.open(log_file, "a+")
55
55
  @log.sync = true
56
56
  @opened = true
57
57
  when NilClass
@@ -118,10 +118,10 @@ module WEBrick
118
118
  # * Otherwise it will return +arg+.inspect.
119
119
  def format(arg)
120
120
  if arg.is_a?(Exception)
121
- "#{arg.class}: #{arg.message}\n\t" <<
121
+ "#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" <<
122
122
  arg.backtrace.join("\n\t") << "\n"
123
123
  elsif arg.respond_to?(:to_str)
124
- arg.to_str
124
+ AccessLog.escape(arg.to_str)
125
125
  else
126
126
  arg.inspect
127
127
  end
@@ -9,10 +9,9 @@
9
9
  #
10
10
  # $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
11
11
 
12
- require 'thread'
13
12
  require 'socket'
14
- require 'webrick/config'
15
- require 'webrick/log'
13
+ require_relative 'config'
14
+ require_relative 'log'
16
15
 
17
16
  module WEBrick
18
17
 
@@ -104,7 +103,7 @@ module WEBrick
104
103
  @shutdown_pipe = nil
105
104
  unless @config[:DoNotListen]
106
105
  if @config[:Listen]
107
- warn(":Listen option is deprecated; use GenericServer#listen")
106
+ warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
108
107
  end
109
108
  listen(@config[:BindAddress], @config[:Port])
110
109
  if @config[:Port] == 0
@@ -158,17 +157,17 @@ module WEBrick
158
157
  server_type.start{
159
158
  @logger.info \
160
159
  "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
160
+ @status = :Running
161
161
  call_callback(:StartCallback)
162
162
 
163
163
  shutdown_pipe = @shutdown_pipe
164
164
 
165
165
  thgroup = ThreadGroup.new
166
- @status = :Running
167
166
  begin
168
167
  while @status == :Running
169
168
  begin
170
169
  sp = shutdown_pipe[0]
171
- if svrs = IO.select([sp, *@listeners], nil, nil, 2.0)
170
+ if svrs = IO.select([sp, *@listeners])
172
171
  if svrs[0].include? sp
173
172
  # swallow shutdown pipe
174
173
  buf = String.new
@@ -252,18 +251,26 @@ module WEBrick
252
251
  # the client socket.
253
252
 
254
253
  def accept_client(svr)
255
- sock = nil
256
- begin
257
- sock = svr.accept
258
- sock.sync = true
259
- Utils::set_non_blocking(sock)
260
- rescue Errno::ECONNRESET, Errno::ECONNABORTED,
261
- Errno::EPROTO, Errno::EINVAL
262
- rescue StandardError => ex
263
- msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
264
- @logger.error msg
254
+ case sock = svr.to_io.accept_nonblock(exception: false)
255
+ when :wait_readable
256
+ nil
257
+ else
258
+ if svr.respond_to?(:start_immediately)
259
+ sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
260
+ sock.sync_close = true
261
+ # we cannot do OpenSSL::SSL::SSLSocket#accept here because
262
+ # a slow client can prevent us from accepting connections
263
+ # from other clients
264
+ end
265
+ sock
265
266
  end
266
- return sock
267
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED,
268
+ Errno::EPROTO, Errno::EINVAL
269
+ nil
270
+ rescue StandardError => ex
271
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
272
+ @logger.error msg
273
+ nil
267
274
  end
268
275
 
269
276
  ##
@@ -286,6 +293,16 @@ module WEBrick
286
293
  @logger.debug "accept: <address unknown>"
287
294
  raise
288
295
  end
296
+ if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately]
297
+ WEBrick::Utils.timeout(@config[:RequestTimeout]) do
298
+ begin
299
+ sock.accept # OpenSSL::SSL::SSLSocket#accept
300
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED,
301
+ Errno::EPROTO, Errno::EINVAL
302
+ Thread.exit
303
+ end
304
+ end
305
+ end
289
306
  call_callback(:AcceptCallback, sock)
290
307
  block ? block.call(sock) : run(sock)
291
308
  rescue Errno::ENOTCONN
@@ -48,6 +48,8 @@ module WEBrick
48
48
  # Number of CA certificates to walk when verifying a certificate chain
49
49
  # :SSLVerifyCallback ::
50
50
  # Custom certificate verification callback
51
+ # :SSLServerNameCallback::
52
+ # Custom servername indication callback
51
53
  # :SSLTimeout ::
52
54
  # Maximum session lifetime
53
55
  # :SSLOptions ::
@@ -128,7 +130,7 @@ module WEBrick
128
130
  aki = ef.create_extension("authorityKeyIdentifier",
129
131
  "keyid:always,issuer:always")
130
132
  cert.add_extension(aki)
131
- cert.sign(rsa, OpenSSL::Digest::SHA1.new)
133
+ cert.sign(rsa, OpenSSL::Digest::SHA256.new)
132
134
 
133
135
  return [ cert, rsa ]
134
136
  end
@@ -145,7 +147,13 @@ module WEBrick
145
147
  # SSL context for the server when run in SSL mode
146
148
 
147
149
  def ssl_context # :nodoc:
148
- @ssl_context ||= nil
150
+ @ssl_context ||= begin
151
+ if @config[:SSLEnable]
152
+ ssl_context = setup_ssl_context(@config)
153
+ @logger.info("\n" + @config[:SSLCertificate].to_text)
154
+ ssl_context
155
+ end
156
+ end
149
157
  end
150
158
 
151
159
  undef listen
@@ -156,10 +164,6 @@ module WEBrick
156
164
  def listen(address, port) # :nodoc:
157
165
  listeners = Utils::create_listeners(address, port)
158
166
  if @config[:SSLEnable]
159
- unless ssl_context
160
- @ssl_context = setup_ssl_context(@config)
161
- @logger.info("\n" + @config[:SSLCertificate].to_text)
162
- end
163
167
  listeners.collect!{|svr|
164
168
  ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
165
169
  ssvr.start_immediately = @config[:SSLStartImmediately]
@@ -177,7 +181,7 @@ module WEBrick
177
181
  unless config[:SSLCertificate]
178
182
  cn = config[:SSLCertName]
179
183
  comment = config[:SSLCertComment]
180
- cert, key = Utils::create_self_signed_cert(1024, cn, comment)
184
+ cert, key = Utils::create_self_signed_cert(2048, cn, comment)
181
185
  config[:SSLCertificate] = cert
182
186
  config[:SSLPrivateKey] = key
183
187
  end
@@ -193,10 +197,19 @@ module WEBrick
193
197
  ctx.verify_mode = config[:SSLVerifyClient]
194
198
  ctx.verify_depth = config[:SSLVerifyDepth]
195
199
  ctx.verify_callback = config[:SSLVerifyCallback]
200
+ ctx.servername_cb = config[:SSLServerNameCallback] || proc { |args| ssl_servername_callback(*args) }
196
201
  ctx.timeout = config[:SSLTimeout]
197
202
  ctx.options = config[:SSLOptions]
198
203
  ctx.ciphers = config[:SSLCiphers]
199
204
  ctx
200
205
  end
206
+
207
+ ##
208
+ # ServerNameIndication callback
209
+
210
+ def ssl_servername_callback(sslsocket, hostname = nil)
211
+ # default
212
+ end
213
+
201
214
  end
202
215
  end
@@ -37,7 +37,7 @@ module WEBrick
37
37
  Process::Sys::setgid(pw.gid)
38
38
  Process::Sys::setuid(pw.uid)
39
39
  else
40
- warn("WEBrick::Utils::su doesn't work on this platform")
40
+ warn("WEBrick::Utils::su doesn't work on this platform", uplevel: 1)
41
41
  end
42
42
  end
43
43
  module_function :su
@@ -91,7 +91,6 @@ module WEBrick
91
91
 
92
92
  ###########
93
93
 
94
- require "thread"
95
94
  require "timeout"
96
95
  require "singleton"
97
96