webrick 1.4.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/webrick/https.rb CHANGED
@@ -9,8 +9,8 @@
9
9
  #
10
10
  # $IPR: https.rb,v 1.15 2003/07/22 19:20:42 gotoyuzo Exp $
11
11
 
12
- require 'webrick/ssl'
13
- require 'webrick/httpserver'
12
+ require_relative 'ssl'
13
+ require_relative 'httpserver'
14
14
 
15
15
  module WEBrick
16
16
  module Config
@@ -10,13 +10,13 @@
10
10
  # $IPR: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $
11
11
 
12
12
  require 'io/wait'
13
- require 'webrick/server'
14
- require 'webrick/httputils'
15
- require 'webrick/httpstatus'
16
- require 'webrick/httprequest'
17
- require 'webrick/httpresponse'
18
- require 'webrick/httpservlet'
19
- require 'webrick/accesslog'
13
+ require_relative 'server'
14
+ require_relative 'httputils'
15
+ require_relative 'httpstatus'
16
+ require_relative 'httprequest'
17
+ require_relative 'httpresponse'
18
+ require_relative 'httpservlet'
19
+ require_relative 'accesslog'
20
20
 
21
21
  module WEBrick
22
22
  class HTTPServerError < ServerError; end
@@ -68,8 +68,8 @@ module WEBrick
68
68
 
69
69
  def run(sock)
70
70
  while true
71
- res = HTTPResponse.new(@config)
72
- req = HTTPRequest.new(@config)
71
+ req = create_request(@config)
72
+ res = create_response(@config)
73
73
  server = self
74
74
  begin
75
75
  timeout = @config[:RequestTimeout]
@@ -224,6 +224,20 @@ module WEBrick
224
224
  }
225
225
  end
226
226
 
227
+ ##
228
+ # Creates the HTTPRequest used when handling the HTTP
229
+ # request. Can be overridden by subclasses.
230
+ def create_request(with_webrick_config)
231
+ HTTPRequest.new(with_webrick_config)
232
+ end
233
+
234
+ ##
235
+ # Creates the HTTPResponse used when handling the HTTP
236
+ # request. Can be overridden by subclasses.
237
+ def create_response(with_webrick_config)
238
+ HTTPResponse.new(with_webrick_config)
239
+ end
240
+
227
241
  ##
228
242
  # Mount table for the path a servlet is mounted on in the directory space
229
243
  # of the server. Users of WEBrick can only access this indirectly via
@@ -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,9 +9,9 @@
9
9
  #
10
10
  # $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $
11
11
 
12
- require 'webrick/htmlutils'
13
- require 'webrick/httputils'
14
- require 'webrick/httpstatus'
12
+ require_relative '../htmlutils'
13
+ require_relative '../httputils'
14
+ require_relative '../httpstatus'
15
15
 
16
16
  module WEBrick
17
17
  module HTTPServlet
@@ -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
@@ -28,6 +28,7 @@ module WEBrick
28
28
  class CGIHandler < AbstractServlet
29
29
  Ruby = RbConfig.ruby # :nodoc:
30
30
  CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc:
31
+ CGIRunnerArray = [Ruby, "#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb".freeze].freeze # :nodoc:
31
32
 
32
33
  ##
33
34
  # Creates a new CGI script servlet for the script at +name+
@@ -36,7 +37,12 @@ module WEBrick
36
37
  super(server, name)
37
38
  @script_filename = name
38
39
  @tempdir = server[:TempDir]
39
- @cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
40
+ interpreter = server[:CGIInterpreter]
41
+ if interpreter.is_a?(Array)
42
+ @cgicmd = CGIRunnerArray + interpreter
43
+ else
44
+ @cgicmd = "#{CGIRunner} #{interpreter}"
45
+ end
40
46
  end
41
47
 
42
48
  # :stopdoc:
@@ -65,9 +71,7 @@ module WEBrick
65
71
  cgi_in.write("%8d" % dump.bytesize)
66
72
  cgi_in.write(dump)
67
73
 
68
- if req.body and req.body.bytesize > 0
69
- cgi_in.write(req.body)
70
- end
74
+ req.body { |chunk| cgi_in.write(chunk) }
71
75
  ensure
72
76
  cgi_in.close
73
77
  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
 
@@ -11,9 +11,9 @@
11
11
 
12
12
  require 'time'
13
13
 
14
- require 'webrick/htmlutils'
15
- require 'webrick/httputils'
16
- require 'webrick/httpstatus'
14
+ require_relative '../htmlutils'
15
+ require_relative '../httputils'
16
+ require_relative '../httpstatus'
17
17
 
18
18
  module WEBrick
19
19
  module HTTPServlet
@@ -55,7 +55,7 @@ module WEBrick
55
55
  else
56
56
  mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
57
57
  res['content-type'] = mtype
58
- res['content-length'] = st.size
58
+ res['content-length'] = st.size.to_s
59
59
  res['last-modified'] = mtime.httpdate
60
60
  res.body = File.open(@local_path, "rb")
61
61
  end
@@ -86,6 +86,35 @@ module WEBrick
86
86
  return false
87
87
  end
88
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
+
89
118
  def make_partial_content(req, res, filename, filesize)
90
119
  mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
91
120
  unless ranges = HTTPUtils::parse_range_header(req['range'])
@@ -96,37 +125,27 @@ module WEBrick
96
125
  if ranges.size > 1
97
126
  time = Time.now
98
127
  boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
99
- body = ''
100
- ranges.each{|range|
101
- first, last = prepare_range(range, filesize)
102
- next if first < 0
103
- io.pos = first
104
- content = io.read(last-first+1)
105
- body << "--" << boundary << CRLF
106
- body << "Content-Type: #{mtype}" << CRLF
107
- body << "Content-Range: bytes #{first}-#{last}/#{filesize}" << CRLF
108
- body << CRLF
109
- body << content
110
- body << CRLF
128
+ parts = []
129
+ ranges.each {|range|
130
+ prange = prepare_range(range, filesize)
131
+ next if prange[0] < 0
132
+ parts.concat(prange)
111
133
  }
112
- raise HTTPStatus::RequestRangeNotSatisfiable if body.empty?
113
- body << "--" << boundary << "--" << CRLF
134
+ raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
114
135
  res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
115
- 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)
116
142
  elsif range = ranges[0]
117
143
  first, last = prepare_range(range, filesize)
118
144
  raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
119
- if last == filesize - 1
120
- content = io.dup
121
- content.pos = first
122
- else
123
- io.pos = first
124
- content = io.read(last-first+1)
125
- end
126
145
  res['content-type'] = mtype
127
146
  res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
128
- res['content-length'] = last - first + 1
129
- res.body = content
147
+ res['content-length'] = (last - first + 1).to_s
148
+ res.body = io.dup
130
149
  else
131
150
  raise HTTPStatus::BadRequest
132
151
  end
@@ -193,9 +212,18 @@ module WEBrick
193
212
 
194
213
  # :stopdoc:
195
214
 
215
+ def set_filesystem_encoding(str)
216
+ enc = Encoding.find('filesystem')
217
+ if enc == Encoding::US_ASCII
218
+ str.b
219
+ else
220
+ str.dup.force_encoding(enc)
221
+ end
222
+ end
223
+
196
224
  def service(req, res)
197
225
  # if this class is mounted on "/" and /~username is requested.
198
- # we're going to override path informations before invoking service.
226
+ # we're going to override path information before invoking service.
199
227
  if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
200
228
  if %r|^(/~([^/]+))| =~ req.path_info
201
229
  script_name, user = $1, $2
@@ -279,7 +307,7 @@ module WEBrick
279
307
  end
280
308
 
281
309
  def exec_handler(req, res)
282
- raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
310
+ raise HTTPStatus::NotFound, "`#{req.path}' not found." unless @root
283
311
  if set_filename(req, res)
284
312
  handler = get_handler(req, res)
285
313
  call_callback(:HandlerCallback, req, res)
@@ -305,11 +333,12 @@ module WEBrick
305
333
  end
306
334
 
307
335
  def set_filename(req, res)
308
- res.filename = @root.dup
336
+ res.filename = @root
309
337
  path_info = req.path_info.scan(%r|/[^/]*|)
310
338
 
311
339
  path_info.unshift("") # dummy for checking @root dir
312
340
  while base = path_info.first
341
+ base = set_filesystem_encoding(base)
313
342
  break if base == "/"
314
343
  break unless File.directory?(File.expand_path(res.filename + base))
315
344
  shift_path_info(req, res, path_info)
@@ -317,6 +346,7 @@ module WEBrick
317
346
  end
318
347
 
319
348
  if base = path_info.first
349
+ base = set_filesystem_encoding(base)
320
350
  if base == "/"
321
351
  if file = search_index_file(req, res)
322
352
  shift_path_info(req, res, path_info, file)
@@ -345,7 +375,7 @@ module WEBrick
345
375
 
346
376
  def shift_path_info(req, res, path_info, base=nil)
347
377
  tmp = path_info.shift
348
- base = base || tmp
378
+ base = base || set_filesystem_encoding(tmp)
349
379
  req.path_info = path_info.join
350
380
  req.script_name << base
351
381
  res.filename = File.expand_path(res.filename + base)
@@ -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
 
@@ -72,6 +72,7 @@ module WEBrick
72
72
  "json" => "application/json",
73
73
  "lha" => "application/octet-stream",
74
74
  "lzh" => "application/octet-stream",
75
+ "mjs" => "application/javascript",
75
76
  "mov" => "video/quicktime",
76
77
  "mpe" => "video/mpeg",
77
78
  "mpeg" => "video/mpeg",
@@ -95,6 +96,7 @@ module WEBrick
95
96
  "tif" => "image/tiff",
96
97
  "tiff" => "image/tiff",
97
98
  "txt" => "text/plain",
99
+ "wasm" => "application/wasm",
98
100
  "xbm" => "image/x-xbitmap",
99
101
  "xhtml" => "text/html",
100
102
  "xls" => "application/vnd.ms-excel",
@@ -161,10 +163,7 @@ module WEBrick
161
163
  end
162
164
  }
163
165
  header.each{|key, values|
164
- values.each{|value|
165
- value.strip!
166
- value.gsub!(/\s+/, " ")
167
- }
166
+ values.each(&:strip!)
168
167
  }
169
168
  header
170
169
  end
@@ -10,8 +10,8 @@
10
10
  # $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
11
11
 
12
12
  require 'socket'
13
- require 'webrick/config'
14
- require 'webrick/log'
13
+ require_relative 'config'
14
+ require_relative 'log'
15
15
 
16
16
  module WEBrick
17
17
 
@@ -102,6 +102,9 @@ module WEBrick
102
102
  @listeners = []
103
103
  @shutdown_pipe = nil
104
104
  unless @config[:DoNotListen]
105
+ raise ArgumentError, "Port must an integer" unless @config[:Port].to_s == @config[:Port].to_i.to_s
106
+
107
+ @config[:Port] = @config[:Port].to_i
105
108
  if @config[:Listen]
106
109
  warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
107
110
  end
data/lib/webrick/ssl.rb CHANGED
@@ -122,7 +122,7 @@ module WEBrick
122
122
  ef.issuer_certificate = cert
123
123
  cert.extensions = [
124
124
  ef.create_extension("basicConstraints","CA:FALSE"),
125
- ef.create_extension("keyUsage", "keyEncipherment"),
125
+ ef.create_extension("keyUsage", "keyEncipherment, digitalSignature, keyAgreement, dataEncipherment"),
126
126
  ef.create_extension("subjectKeyIdentifier", "hash"),
127
127
  ef.create_extension("extendedKeyUsage", "serverAuth"),
128
128
  ef.create_extension("nsComment", comment),
@@ -130,7 +130,7 @@ module WEBrick
130
130
  aki = ef.create_extension("authorityKeyIdentifier",
131
131
  "keyid:always,issuer:always")
132
132
  cert.add_extension(aki)
133
- cert.sign(rsa, OpenSSL::Digest::SHA1.new)
133
+ cert.sign(rsa, "SHA256")
134
134
 
135
135
  return [ cert, rsa ]
136
136
  end
@@ -181,7 +181,7 @@ module WEBrick
181
181
  unless config[:SSLCertificate]
182
182
  cn = config[:SSLCertName]
183
183
  comment = config[:SSLCertComment]
184
- cert, key = Utils::create_self_signed_cert(1024, cn, comment)
184
+ cert, key = Utils::create_self_signed_cert(2048, cn, comment)
185
185
  config[:SSLCertificate] = cert
186
186
  config[:SSLPrivateKey] = key
187
187
  end
data/lib/webrick/utils.rb CHANGED
@@ -45,12 +45,7 @@ module WEBrick
45
45
  ##
46
46
  # The server hostname
47
47
  def getservername
48
- host = Socket::gethostname
49
- begin
50
- Socket::gethostbyname(host)[0]
51
- rescue
52
- host
53
- end
48
+ Socket::gethostname
54
49
  end
55
50
  module_function :getservername
56
51
 
@@ -14,5 +14,5 @@ module WEBrick
14
14
  ##
15
15
  # The WEBrick version
16
16
 
17
- VERSION = "1.4.2"
17
+ VERSION = "1.7.0"
18
18
  end
data/webrick.gemspec ADDED
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+ begin
3
+ require_relative 'lib/webrick/version'
4
+ rescue LoadError
5
+ # for Ruby core repository
6
+ require_relative 'version'
7
+ end
8
+
9
+ Gem::Specification.new do |s|
10
+ s.name = "webrick"
11
+ s.version = WEBrick::VERSION
12
+ s.summary = "HTTP server toolkit"
13
+ s.description = "WEBrick is an HTTP server toolkit that can be configured as an HTTPS server, a proxy server, and a virtual-host server."
14
+
15
+ s.require_path = %w{lib}
16
+ s.files = [
17
+ "Gemfile",
18
+ "LICENSE.txt",
19
+ "README.md",
20
+ "Rakefile",
21
+ "bin/console",
22
+ "bin/setup",
23
+ "lib/webrick.rb",
24
+ "lib/webrick/accesslog.rb",
25
+ "lib/webrick/cgi.rb",
26
+ "lib/webrick/compat.rb",
27
+ "lib/webrick/config.rb",
28
+ "lib/webrick/cookie.rb",
29
+ "lib/webrick/htmlutils.rb",
30
+ "lib/webrick/httpauth.rb",
31
+ "lib/webrick/httpauth/authenticator.rb",
32
+ "lib/webrick/httpauth/basicauth.rb",
33
+ "lib/webrick/httpauth/digestauth.rb",
34
+ "lib/webrick/httpauth/htdigest.rb",
35
+ "lib/webrick/httpauth/htgroup.rb",
36
+ "lib/webrick/httpauth/htpasswd.rb",
37
+ "lib/webrick/httpauth/userdb.rb",
38
+ "lib/webrick/httpproxy.rb",
39
+ "lib/webrick/httprequest.rb",
40
+ "lib/webrick/httpresponse.rb",
41
+ "lib/webrick/https.rb",
42
+ "lib/webrick/httpserver.rb",
43
+ "lib/webrick/httpservlet.rb",
44
+ "lib/webrick/httpservlet/abstract.rb",
45
+ "lib/webrick/httpservlet/cgi_runner.rb",
46
+ "lib/webrick/httpservlet/cgihandler.rb",
47
+ "lib/webrick/httpservlet/erbhandler.rb",
48
+ "lib/webrick/httpservlet/filehandler.rb",
49
+ "lib/webrick/httpservlet/prochandler.rb",
50
+ "lib/webrick/httpstatus.rb",
51
+ "lib/webrick/httputils.rb",
52
+ "lib/webrick/httpversion.rb",
53
+ "lib/webrick/log.rb",
54
+ "lib/webrick/server.rb",
55
+ "lib/webrick/ssl.rb",
56
+ "lib/webrick/utils.rb",
57
+ "lib/webrick/version.rb",
58
+ "webrick.gemspec",
59
+ ]
60
+ s.required_ruby_version = ">= 2.3.0"
61
+
62
+ s.authors = ["TAKAHASHI Masayoshi", "GOTOU YUUZOU", "Eric Wong"]
63
+ s.email = [nil, nil, 'normal@ruby-lang.org']
64
+ s.homepage = "https://github.com/ruby/webrick"
65
+ s.licenses = ["Ruby", "BSD-2-Clause"]
66
+
67
+ if s.respond_to?(:metadata=)
68
+ s.metadata = {
69
+ "bug_tracker_uri" => "https://github.com/ruby/webrick/issues",
70
+ }
71
+ end
72
+
73
+ s.add_development_dependency "rake"
74
+ end