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.
- checksums.yaml +7 -0
- data/lib/webrick.rb +6 -6
- data/lib/webrick/accesslog.rb +9 -1
- data/lib/webrick/cgi.rb +58 -5
- data/lib/webrick/compat.rb +2 -1
- data/lib/webrick/config.rb +47 -10
- data/lib/webrick/cookie.rb +69 -7
- data/lib/webrick/htmlutils.rb +4 -2
- data/lib/webrick/httpauth.rb +6 -5
- data/lib/webrick/httpauth/authenticator.rb +13 -8
- data/lib/webrick/httpauth/basicauth.rb +16 -8
- data/lib/webrick/httpauth/digestauth.rb +35 -32
- data/lib/webrick/httpauth/htdigest.rb +12 -8
- data/lib/webrick/httpauth/htgroup.rb +10 -6
- data/lib/webrick/httpauth/htpasswd.rb +46 -9
- data/lib/webrick/httpauth/userdb.rb +1 -0
- data/lib/webrick/httpproxy.rb +93 -48
- data/lib/webrick/httprequest.rb +192 -27
- data/lib/webrick/httpresponse.rb +182 -62
- data/lib/webrick/https.rb +90 -2
- data/lib/webrick/httpserver.rb +45 -15
- data/lib/webrick/httpservlet.rb +6 -5
- data/lib/webrick/httpservlet/abstract.rb +5 -6
- data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
- data/lib/webrick/httpservlet/cgihandler.rb +22 -10
- data/lib/webrick/httpservlet/erbhandler.rb +4 -3
- data/lib/webrick/httpservlet/filehandler.rb +136 -65
- data/lib/webrick/httpservlet/prochandler.rb +15 -1
- data/lib/webrick/httpstatus.rb +24 -14
- data/lib/webrick/httputils.rb +132 -13
- data/lib/webrick/httpversion.rb +28 -1
- data/lib/webrick/log.rb +25 -5
- data/lib/webrick/server.rb +234 -74
- data/lib/webrick/ssl.rb +100 -12
- data/lib/webrick/utils.rb +98 -69
- data/lib/webrick/version.rb +6 -1
- metadata +66 -72
- data/README.txt +0 -21
- data/sample/webrick/demo-app.rb +0 -66
- data/sample/webrick/demo-multipart.cgi +0 -12
- data/sample/webrick/demo-servlet.rb +0 -6
- data/sample/webrick/demo-urlencoded.cgi +0 -12
- data/sample/webrick/hello.cgi +0 -11
- data/sample/webrick/hello.rb +0 -8
- data/sample/webrick/httpd.rb +0 -23
- data/sample/webrick/httpproxy.rb +0 -25
- data/sample/webrick/httpsd.rb +0 -33
- data/test/openssl/utils.rb +0 -313
- data/test/ruby/envutil.rb +0 -208
- data/test/webrick/test_cgi.rb +0 -134
- data/test/webrick/test_cookie.rb +0 -131
- data/test/webrick/test_filehandler.rb +0 -285
- data/test/webrick/test_httpauth.rb +0 -167
- data/test/webrick/test_httpproxy.rb +0 -282
- data/test/webrick/test_httprequest.rb +0 -411
- data/test/webrick/test_httpresponse.rb +0 -49
- data/test/webrick/test_httpserver.rb +0 -305
- data/test/webrick/test_httputils.rb +0 -96
- data/test/webrick/test_httpversion.rb +0 -40
- data/test/webrick/test_server.rb +0 -67
- data/test/webrick/test_utils.rb +0 -64
- data/test/webrick/utils.rb +0 -58
- data/test/webrick/webrick.cgi +0 -36
- data/test/webrick/webrick_long_filename.cgi +0 -36
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# prochandler.rb -- ProcHandler Class
|
3
4
|
#
|
@@ -8,12 +9,24 @@
|
|
8
9
|
#
|
9
10
|
# $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $
|
10
11
|
|
11
|
-
|
12
|
+
require_relative 'abstract'
|
12
13
|
|
13
14
|
module WEBrick
|
14
15
|
module HTTPServlet
|
15
16
|
|
17
|
+
##
|
18
|
+
# Mounts a proc at a path that accepts a request and response.
|
19
|
+
#
|
20
|
+
# Instead of mounting this servlet with WEBrick::HTTPServer#mount use
|
21
|
+
# WEBrick::HTTPServer#mount_proc:
|
22
|
+
#
|
23
|
+
# server.mount_proc '/' do |req, res|
|
24
|
+
# res.body = 'it worked!'
|
25
|
+
# res.status = 200
|
26
|
+
# end
|
27
|
+
|
16
28
|
class ProcHandler < AbstractServlet
|
29
|
+
# :stopdoc:
|
17
30
|
def get_instance(server, *options)
|
18
31
|
self
|
19
32
|
end
|
@@ -27,6 +40,7 @@ module WEBrick
|
|
27
40
|
end
|
28
41
|
|
29
42
|
alias do_POST do_GET
|
43
|
+
# :startdoc:
|
30
44
|
end
|
31
45
|
|
32
46
|
end
|
data/lib/webrick/httpstatus.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#--
|
2
3
|
# httpstatus.rb -- HTTPStatus Class
|
3
4
|
#
|
@@ -8,6 +9,8 @@
|
|
8
9
|
#
|
9
10
|
# $IPR: httpstatus.rb,v 1.11 2003/03/24 20:18:55 gotoyuzo Exp $
|
10
11
|
|
12
|
+
require_relative 'accesslog'
|
13
|
+
|
11
14
|
module WEBrick
|
12
15
|
|
13
16
|
##
|
@@ -20,26 +23,22 @@ module WEBrick
|
|
20
23
|
##
|
21
24
|
# Root of the HTTP status class hierarchy
|
22
25
|
class Status < StandardError
|
23
|
-
def initialize(*args) # :nodoc:
|
24
|
-
args[0] = AccessLog.escape(args[0]) unless args.empty?
|
25
|
-
super(*args)
|
26
|
-
end
|
27
26
|
class << self
|
28
27
|
attr_reader :code, :reason_phrase # :nodoc:
|
29
28
|
end
|
30
|
-
|
29
|
+
|
31
30
|
# Returns the HTTP status code
|
32
31
|
def code() self::class::code end
|
33
|
-
|
32
|
+
|
34
33
|
# Returns the HTTP status description
|
35
34
|
def reason_phrase() self::class::reason_phrase end
|
36
|
-
|
35
|
+
|
37
36
|
alias to_i code # :nodoc:
|
38
37
|
end
|
39
38
|
|
40
39
|
# Root of the HTTP info statuses
|
41
40
|
class Info < Status; end
|
42
|
-
# Root of the HTTP
|
41
|
+
# Root of the HTTP success statuses
|
43
42
|
class Success < Status; end
|
44
43
|
# Root of the HTTP redirect statuses
|
45
44
|
class Redirect < Status; end
|
@@ -63,6 +62,7 @@ module WEBrick
|
|
63
62
|
204 => 'No Content',
|
64
63
|
205 => 'Reset Content',
|
65
64
|
206 => 'Partial Content',
|
65
|
+
207 => 'Multi-Status',
|
66
66
|
300 => 'Multiple Choices',
|
67
67
|
301 => 'Moved Permanently',
|
68
68
|
302 => 'Found',
|
@@ -88,12 +88,22 @@ module WEBrick
|
|
88
88
|
415 => 'Unsupported Media Type',
|
89
89
|
416 => 'Request Range Not Satisfiable',
|
90
90
|
417 => 'Expectation Failed',
|
91
|
+
422 => 'Unprocessable Entity',
|
92
|
+
423 => 'Locked',
|
93
|
+
424 => 'Failed Dependency',
|
94
|
+
426 => 'Upgrade Required',
|
95
|
+
428 => 'Precondition Required',
|
96
|
+
429 => 'Too Many Requests',
|
97
|
+
431 => 'Request Header Fields Too Large',
|
98
|
+
451 => 'Unavailable For Legal Reasons',
|
91
99
|
500 => 'Internal Server Error',
|
92
100
|
501 => 'Not Implemented',
|
93
101
|
502 => 'Bad Gateway',
|
94
102
|
503 => 'Service Unavailable',
|
95
103
|
504 => 'Gateway Timeout',
|
96
|
-
505 => 'HTTP Version Not Supported'
|
104
|
+
505 => 'HTTP Version Not Supported',
|
105
|
+
507 => 'Insufficient Storage',
|
106
|
+
511 => 'Network Authentication Required',
|
97
107
|
}
|
98
108
|
|
99
109
|
# Maps a status code to the corresponding Status class
|
@@ -136,31 +146,31 @@ module WEBrick
|
|
136
146
|
def info?(code)
|
137
147
|
code.to_i >= 100 and code.to_i < 200
|
138
148
|
end
|
139
|
-
|
149
|
+
|
140
150
|
##
|
141
151
|
# Is +code+ a successful status?
|
142
152
|
def success?(code)
|
143
153
|
code.to_i >= 200 and code.to_i < 300
|
144
154
|
end
|
145
|
-
|
155
|
+
|
146
156
|
##
|
147
157
|
# Is +code+ a redirection status?
|
148
158
|
def redirect?(code)
|
149
159
|
code.to_i >= 300 and code.to_i < 400
|
150
160
|
end
|
151
|
-
|
161
|
+
|
152
162
|
##
|
153
163
|
# Is +code+ an error status?
|
154
164
|
def error?(code)
|
155
165
|
code.to_i >= 400 and code.to_i < 600
|
156
166
|
end
|
157
|
-
|
167
|
+
|
158
168
|
##
|
159
169
|
# Is +code+ a client error status?
|
160
170
|
def client_error?(code)
|
161
171
|
code.to_i >= 400 and code.to_i < 500
|
162
172
|
end
|
163
|
-
|
173
|
+
|
164
174
|
##
|
165
175
|
# Is +code+ a server error status?
|
166
176
|
def server_error?(code)
|
data/lib/webrick/httputils.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# httputils.rb -- HTTPUtils Module
|
3
4
|
#
|
@@ -12,12 +13,21 @@ require 'socket'
|
|
12
13
|
require 'tempfile'
|
13
14
|
|
14
15
|
module WEBrick
|
15
|
-
CR = "\x0d"
|
16
|
-
LF = "\x0a"
|
17
|
-
CRLF = "\x0d\x0a"
|
16
|
+
CR = "\x0d" # :nodoc:
|
17
|
+
LF = "\x0a" # :nodoc:
|
18
|
+
CRLF = "\x0d\x0a" # :nodoc:
|
19
|
+
|
20
|
+
##
|
21
|
+
# HTTPUtils provides utility methods for working with the HTTP protocol.
|
22
|
+
#
|
23
|
+
# This module is generally used internally by WEBrick
|
18
24
|
|
19
25
|
module HTTPUtils
|
20
26
|
|
27
|
+
##
|
28
|
+
# Normalizes a request path. Raises an exception if the path cannot be
|
29
|
+
# normalized.
|
30
|
+
|
21
31
|
def normalize_path(path)
|
22
32
|
raise "abnormal path `#{path}'" if path[0] != ?/
|
23
33
|
ret = path.dup
|
@@ -31,7 +41,8 @@ module WEBrick
|
|
31
41
|
end
|
32
42
|
module_function :normalize_path
|
33
43
|
|
34
|
-
|
44
|
+
##
|
45
|
+
# Default mime types
|
35
46
|
|
36
47
|
DefaultMimeTypes = {
|
37
48
|
"ai" => "application/postscript",
|
@@ -58,6 +69,7 @@ module WEBrick
|
|
58
69
|
"jpeg" => "image/jpeg",
|
59
70
|
"jpg" => "image/jpeg",
|
60
71
|
"js" => "application/javascript",
|
72
|
+
"json" => "application/json",
|
61
73
|
"lha" => "application/octet-stream",
|
62
74
|
"lzh" => "application/octet-stream",
|
63
75
|
"mov" => "video/quicktime",
|
@@ -92,8 +104,12 @@ module WEBrick
|
|
92
104
|
"zip" => "application/zip",
|
93
105
|
}
|
94
106
|
|
95
|
-
|
107
|
+
##
|
108
|
+
# Loads Apache-compatible mime.types in +file+.
|
109
|
+
|
96
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.
|
97
113
|
open(file){ |io|
|
98
114
|
hash = Hash.new
|
99
115
|
io.each{ |line|
|
@@ -109,6 +125,10 @@ module WEBrick
|
|
109
125
|
end
|
110
126
|
module_function :load_mime_types
|
111
127
|
|
128
|
+
##
|
129
|
+
# Returns the mime type of +filename+ from the list in +mime_tab+. If no
|
130
|
+
# mime type was found application/octet-stream is returned.
|
131
|
+
|
112
132
|
def mime_type(filename, mime_tab)
|
113
133
|
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
114
134
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
@@ -116,7 +136,9 @@ module WEBrick
|
|
116
136
|
end
|
117
137
|
module_function :mime_type
|
118
138
|
|
119
|
-
|
139
|
+
##
|
140
|
+
# Parses an HTTP header +raw+ into a hash of header fields with an Array
|
141
|
+
# of values.
|
120
142
|
|
121
143
|
def parse_header(raw)
|
122
144
|
header = Hash.new([].freeze)
|
@@ -148,12 +170,18 @@ module WEBrick
|
|
148
170
|
end
|
149
171
|
module_function :parse_header
|
150
172
|
|
173
|
+
##
|
174
|
+
# Splits a header value +str+ according to HTTP specification.
|
175
|
+
|
151
176
|
def split_header_value(str)
|
152
177
|
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
|
153
178
|
(?:,\s*|\Z)'xn).flatten
|
154
179
|
end
|
155
180
|
module_function :split_header_value
|
156
181
|
|
182
|
+
##
|
183
|
+
# Parses a Range header value +ranges_specifier+
|
184
|
+
|
157
185
|
def parse_range_header(ranges_specifier)
|
158
186
|
if /^bytes=(.*)/ =~ ranges_specifier
|
159
187
|
byte_range_set = split_header_value($1)
|
@@ -169,6 +197,9 @@ module WEBrick
|
|
169
197
|
end
|
170
198
|
module_function :parse_range_header
|
171
199
|
|
200
|
+
##
|
201
|
+
# Parses q values in +value+ as used in Accept headers.
|
202
|
+
|
172
203
|
def parse_qvalues(value)
|
173
204
|
tmp = []
|
174
205
|
if value
|
@@ -187,7 +218,8 @@ module WEBrick
|
|
187
218
|
end
|
188
219
|
module_function :parse_qvalues
|
189
220
|
|
190
|
-
|
221
|
+
##
|
222
|
+
# Removes quotes and escapes from +str+
|
191
223
|
|
192
224
|
def dequote(str)
|
193
225
|
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
@@ -196,20 +228,43 @@ module WEBrick
|
|
196
228
|
end
|
197
229
|
module_function :dequote
|
198
230
|
|
231
|
+
##
|
232
|
+
# Quotes and escapes quotes in +str+
|
233
|
+
|
199
234
|
def quote(str)
|
200
235
|
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
|
201
236
|
end
|
202
237
|
module_function :quote
|
203
238
|
|
204
|
-
|
239
|
+
##
|
240
|
+
# Stores multipart form data. FormData objects are created when
|
241
|
+
# WEBrick::HTTPUtils.parse_form_data is called.
|
205
242
|
|
206
243
|
class FormData < String
|
207
|
-
EmptyRawHeader = [].freeze
|
208
|
-
EmptyHeader = {}.freeze
|
244
|
+
EmptyRawHeader = [].freeze # :nodoc:
|
245
|
+
EmptyHeader = {}.freeze # :nodoc:
|
246
|
+
|
247
|
+
##
|
248
|
+
# The name of the form data part
|
249
|
+
|
250
|
+
attr_accessor :name
|
209
251
|
|
210
|
-
|
252
|
+
##
|
253
|
+
# The filename of the form data part
|
254
|
+
|
255
|
+
attr_accessor :filename
|
256
|
+
|
257
|
+
attr_accessor :next_data # :nodoc:
|
211
258
|
protected :next_data
|
212
259
|
|
260
|
+
##
|
261
|
+
# Creates a new FormData object.
|
262
|
+
#
|
263
|
+
# +args+ is an Array of form data entries. One FormData will be created
|
264
|
+
# for each entry.
|
265
|
+
#
|
266
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
267
|
+
|
213
268
|
def initialize(*args)
|
214
269
|
@name = @filename = @next_data = nil
|
215
270
|
if args.empty?
|
@@ -226,6 +281,9 @@ module WEBrick
|
|
226
281
|
end
|
227
282
|
end
|
228
283
|
|
284
|
+
##
|
285
|
+
# Retrieves the header at the first entry in +key+
|
286
|
+
|
229
287
|
def [](*key)
|
230
288
|
begin
|
231
289
|
@header[key[0].downcase].join(", ")
|
@@ -234,6 +292,12 @@ module WEBrick
|
|
234
292
|
end
|
235
293
|
end
|
236
294
|
|
295
|
+
##
|
296
|
+
# Adds +str+ to this FormData which may be the body, a header or a
|
297
|
+
# header entry.
|
298
|
+
#
|
299
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
300
|
+
|
237
301
|
def <<(str)
|
238
302
|
if @header
|
239
303
|
super
|
@@ -249,6 +313,11 @@ module WEBrick
|
|
249
313
|
self
|
250
314
|
end
|
251
315
|
|
316
|
+
##
|
317
|
+
# Adds +data+ at the end of the chain of entries
|
318
|
+
#
|
319
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you.
|
320
|
+
|
252
321
|
def append_data(data)
|
253
322
|
tmp = self
|
254
323
|
while tmp
|
@@ -261,6 +330,9 @@ module WEBrick
|
|
261
330
|
self
|
262
331
|
end
|
263
332
|
|
333
|
+
##
|
334
|
+
# Yields each entry in this FormData
|
335
|
+
|
264
336
|
def each_data
|
265
337
|
tmp = self
|
266
338
|
while tmp
|
@@ -270,6 +342,9 @@ module WEBrick
|
|
270
342
|
end
|
271
343
|
end
|
272
344
|
|
345
|
+
##
|
346
|
+
# Returns all the FormData as an Array
|
347
|
+
|
273
348
|
def list
|
274
349
|
ret = []
|
275
350
|
each_data{|data|
|
@@ -278,13 +353,22 @@ module WEBrick
|
|
278
353
|
ret
|
279
354
|
end
|
280
355
|
|
356
|
+
##
|
357
|
+
# A FormData will behave like an Array
|
358
|
+
|
281
359
|
alias :to_ary :list
|
282
360
|
|
361
|
+
##
|
362
|
+
# This FormData's body
|
363
|
+
|
283
364
|
def to_s
|
284
365
|
String.new(self)
|
285
366
|
end
|
286
367
|
end
|
287
368
|
|
369
|
+
##
|
370
|
+
# Parses the query component of a URI in +str+
|
371
|
+
|
288
372
|
def parse_query(str)
|
289
373
|
query = Hash.new
|
290
374
|
if str
|
@@ -306,6 +390,9 @@ module WEBrick
|
|
306
390
|
end
|
307
391
|
module_function :parse_query
|
308
392
|
|
393
|
+
##
|
394
|
+
# Parses form data in +io+ with the given +boundary+
|
395
|
+
|
309
396
|
def parse_form_data(io, boundary)
|
310
397
|
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
|
311
398
|
form_data = Hash.new
|
@@ -350,10 +437,22 @@ module WEBrick
|
|
350
437
|
|
351
438
|
module_function
|
352
439
|
|
440
|
+
# :stopdoc:
|
441
|
+
|
353
442
|
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
|
354
443
|
def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
|
355
|
-
def _escape(str, regex)
|
356
|
-
|
444
|
+
def _escape(str, regex)
|
445
|
+
str = str.b
|
446
|
+
str.gsub!(regex) {"%%%02X" % $1.ord}
|
447
|
+
# %-escaped string should contain US-ASCII only
|
448
|
+
str.force_encoding(Encoding::US_ASCII)
|
449
|
+
end
|
450
|
+
def _unescape(str, regex)
|
451
|
+
str = str.b
|
452
|
+
str.gsub!(regex) {$1.hex.chr}
|
453
|
+
# encoding of %-unescaped string is unknown
|
454
|
+
str
|
455
|
+
end
|
357
456
|
|
358
457
|
UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
|
359
458
|
UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
|
@@ -361,24 +460,41 @@ module WEBrick
|
|
361
460
|
ESCAPED = /%([0-9a-fA-F]{2})/
|
362
461
|
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
|
363
462
|
|
463
|
+
# :startdoc:
|
464
|
+
|
465
|
+
##
|
466
|
+
# Escapes HTTP reserved and unwise characters in +str+
|
467
|
+
|
364
468
|
def escape(str)
|
365
469
|
_escape(str, UNESCAPED)
|
366
470
|
end
|
367
471
|
|
472
|
+
##
|
473
|
+
# Unescapes HTTP reserved and unwise characters in +str+
|
474
|
+
|
368
475
|
def unescape(str)
|
369
476
|
_unescape(str, ESCAPED)
|
370
477
|
end
|
371
478
|
|
479
|
+
##
|
480
|
+
# Escapes form reserved characters in +str+
|
481
|
+
|
372
482
|
def escape_form(str)
|
373
483
|
ret = _escape(str, UNESCAPED_FORM)
|
374
484
|
ret.gsub!(/ /, "+")
|
375
485
|
ret
|
376
486
|
end
|
377
487
|
|
488
|
+
##
|
489
|
+
# Unescapes form reserved characters in +str+
|
490
|
+
|
378
491
|
def unescape_form(str)
|
379
492
|
_unescape(str.gsub(/\+/, " "), ESCAPED)
|
380
493
|
end
|
381
494
|
|
495
|
+
##
|
496
|
+
# Escapes path +str+
|
497
|
+
|
382
498
|
def escape_path(str)
|
383
499
|
result = ""
|
384
500
|
str.scan(%r{/([^/]*)}).each{|i|
|
@@ -387,6 +503,9 @@ module WEBrick
|
|
387
503
|
return result
|
388
504
|
end
|
389
505
|
|
506
|
+
##
|
507
|
+
# Escapes 8 bit characters in +str+
|
508
|
+
|
390
509
|
def escape8bit(str)
|
391
510
|
_escape(str, NONASCII)
|
392
511
|
end
|