rubysl-webrick 1.0.0 → 2.0.0
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.
- checksums.yaml +14 -6
- data/.travis.yml +5 -6
- data/lib/rubysl/webrick/version.rb +1 -1
- data/lib/rubysl/webrick/webrick.rb +199 -2
- data/lib/webrick/accesslog.rb +96 -5
- data/lib/webrick/cgi.rb +80 -29
- data/lib/webrick/compat.rb +20 -0
- data/lib/webrick/config.rb +59 -5
- data/lib/webrick/cookie.rb +66 -5
- data/lib/webrick/htmlutils.rb +4 -1
- data/lib/webrick/httpauth.rb +53 -3
- data/lib/webrick/httpauth/authenticator.rb +53 -16
- data/lib/webrick/httpauth/basicauth.rb +45 -2
- data/lib/webrick/httpauth/digestauth.rb +82 -17
- data/lib/webrick/httpauth/htdigest.rb +38 -1
- data/lib/webrick/httpauth/htgroup.rb +32 -0
- data/lib/webrick/httpauth/htpasswd.rb +40 -2
- data/lib/webrick/httpauth/userdb.rb +27 -4
- data/lib/webrick/httpproxy.rb +197 -112
- data/lib/webrick/httprequest.rb +268 -50
- data/lib/webrick/httpresponse.rb +170 -33
- data/lib/webrick/https.rb +26 -3
- data/lib/webrick/httpserver.rb +75 -7
- data/lib/webrick/httpservlet/abstract.rb +88 -6
- data/lib/webrick/httpservlet/cgi_runner.rb +5 -4
- data/lib/webrick/httpservlet/cgihandler.rb +37 -18
- data/lib/webrick/httpservlet/erbhandler.rb +40 -7
- data/lib/webrick/httpservlet/filehandler.rb +116 -28
- data/lib/webrick/httpservlet/prochandler.rb +17 -4
- data/lib/webrick/httpstatus.rb +86 -18
- data/lib/webrick/httputils.rb +131 -23
- data/lib/webrick/httpversion.rb +28 -2
- data/lib/webrick/log.rb +72 -5
- data/lib/webrick/server.rb +158 -33
- data/lib/webrick/ssl.rb +78 -9
- data/lib/webrick/utils.rb +151 -5
- data/lib/webrick/version.rb +5 -1
- data/rubysl-webrick.gemspec +0 -1
- metadata +12 -24
data/lib/webrick/httpversion.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#--
|
2
2
|
# HTTPVersion.rb -- presentation of HTTP version
|
3
3
|
#
|
4
4
|
# Author: IPR -- Internet Programming with Ruby -- writers
|
@@ -8,15 +8,33 @@
|
|
8
8
|
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
|
9
9
|
|
10
10
|
module WEBrick
|
11
|
+
|
12
|
+
##
|
13
|
+
# Represents an HTTP protocol version
|
14
|
+
|
11
15
|
class HTTPVersion
|
12
16
|
include Comparable
|
13
17
|
|
14
|
-
|
18
|
+
##
|
19
|
+
# The major protocol version number
|
20
|
+
|
21
|
+
attr_accessor :major
|
22
|
+
|
23
|
+
##
|
24
|
+
# The minor protocol version number
|
25
|
+
|
26
|
+
attr_accessor :minor
|
27
|
+
|
28
|
+
##
|
29
|
+
# Converts +version+ into an HTTPVersion
|
15
30
|
|
16
31
|
def self.convert(version)
|
17
32
|
version.is_a?(self) ? version : new(version)
|
18
33
|
end
|
19
34
|
|
35
|
+
##
|
36
|
+
# Creates a new HTTPVersion from +version+.
|
37
|
+
|
20
38
|
def initialize(version)
|
21
39
|
case version
|
22
40
|
when HTTPVersion
|
@@ -32,6 +50,10 @@ module WEBrick
|
|
32
50
|
end
|
33
51
|
end
|
34
52
|
|
53
|
+
##
|
54
|
+
# Compares this version with +other+ according to the HTTP specification
|
55
|
+
# rules.
|
56
|
+
|
35
57
|
def <=>(other)
|
36
58
|
unless other.is_a?(self.class)
|
37
59
|
other = self.class.new(other)
|
@@ -42,6 +64,10 @@ module WEBrick
|
|
42
64
|
return ret
|
43
65
|
end
|
44
66
|
|
67
|
+
##
|
68
|
+
# The HTTP version as show in the HTTP request and response. For example,
|
69
|
+
# "1.1"
|
70
|
+
|
45
71
|
def to_s
|
46
72
|
format("%d.%d", @major, @minor)
|
47
73
|
end
|
data/lib/webrick/log.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#--
|
2
2
|
# log.rb -- Log Class
|
3
3
|
#
|
4
4
|
# Author: IPR -- Internet Programming with Ruby -- writers
|
@@ -9,12 +9,43 @@
|
|
9
9
|
# $IPR: log.rb,v 1.26 2002/10/06 17:06:10 gotoyuzo Exp $
|
10
10
|
|
11
11
|
module WEBrick
|
12
|
+
|
13
|
+
##
|
14
|
+
# A generic logging class
|
15
|
+
|
12
16
|
class BasicLog
|
13
|
-
# log-level constant
|
14
|
-
FATAL, ERROR, WARN, INFO, DEBUG = 1, 2, 3, 4, 5
|
15
17
|
|
18
|
+
# Fatal log level which indicates a server crash
|
19
|
+
|
20
|
+
FATAL = 1
|
21
|
+
|
22
|
+
# Error log level which indicates a recoverable error
|
23
|
+
|
24
|
+
ERROR = 2
|
25
|
+
|
26
|
+
# Warning log level which indicates a possible problem
|
27
|
+
|
28
|
+
WARN = 3
|
29
|
+
|
30
|
+
# Information log level which indicates possibly useful information
|
31
|
+
|
32
|
+
INFO = 4
|
33
|
+
|
34
|
+
# Debugging error level for messages used in server development or
|
35
|
+
# debugging
|
36
|
+
|
37
|
+
DEBUG = 5
|
38
|
+
|
39
|
+
# log-level, messages above this level will be logged
|
16
40
|
attr_accessor :level
|
17
41
|
|
42
|
+
##
|
43
|
+
# Initializes a new logger for +log_file+ that outputs messages at +level+
|
44
|
+
# or higher. +log_file+ can be a filename, an IO-like object that
|
45
|
+
# responds to #<< or nil which outputs to $stderr.
|
46
|
+
#
|
47
|
+
# If no level is given INFO is chosen by default
|
48
|
+
|
18
49
|
def initialize(log_file=nil, level=nil)
|
19
50
|
@level = level || INFO
|
20
51
|
case log_file
|
@@ -29,11 +60,17 @@ module WEBrick
|
|
29
60
|
end
|
30
61
|
end
|
31
62
|
|
63
|
+
##
|
64
|
+
# Closes the logger (also closes the log device associated to the logger)
|
32
65
|
def close
|
33
66
|
@log.close if @opened
|
34
67
|
@log = nil
|
35
68
|
end
|
36
69
|
|
70
|
+
##
|
71
|
+
# Logs +data+ at +level+ if the given level is above the current log
|
72
|
+
# level.
|
73
|
+
|
37
74
|
def log(level, data)
|
38
75
|
if @log && level <= @level
|
39
76
|
data += "\n" if /\n\Z/ !~ data
|
@@ -41,26 +78,45 @@ module WEBrick
|
|
41
78
|
end
|
42
79
|
end
|
43
80
|
|
81
|
+
##
|
82
|
+
# Synonym for log(INFO, obj.to_s)
|
44
83
|
def <<(obj)
|
45
84
|
log(INFO, obj.to_s)
|
46
85
|
end
|
47
86
|
|
87
|
+
# Shortcut for logging a FATAL message
|
48
88
|
def fatal(msg) log(FATAL, "FATAL " << format(msg)); end
|
89
|
+
# Shortcut for logging an ERROR message
|
49
90
|
def error(msg) log(ERROR, "ERROR " << format(msg)); end
|
91
|
+
# Shortcut for logging a WARN message
|
50
92
|
def warn(msg) log(WARN, "WARN " << format(msg)); end
|
93
|
+
# Shortcut for logging an INFO message
|
51
94
|
def info(msg) log(INFO, "INFO " << format(msg)); end
|
95
|
+
# Shortcut for logging a DEBUG message
|
52
96
|
def debug(msg) log(DEBUG, "DEBUG " << format(msg)); end
|
53
97
|
|
98
|
+
# Will the logger output FATAL messages?
|
54
99
|
def fatal?; @level >= FATAL; end
|
100
|
+
# Will the logger output ERROR messages?
|
55
101
|
def error?; @level >= ERROR; end
|
102
|
+
# Will the logger output WARN messages?
|
56
103
|
def warn?; @level >= WARN; end
|
104
|
+
# Will the logger output INFO messages?
|
57
105
|
def info?; @level >= INFO; end
|
106
|
+
# Will the logger output DEBUG messages?
|
58
107
|
def debug?; @level >= DEBUG; end
|
59
108
|
|
60
109
|
private
|
61
110
|
|
111
|
+
##
|
112
|
+
# Formats +arg+ for the logger
|
113
|
+
#
|
114
|
+
# * If +arg+ is an Exception, it will format the error message and
|
115
|
+
# the back trace.
|
116
|
+
# * If +arg+ responds to #to_str, it will return it.
|
117
|
+
# * Otherwise it will return +arg+.inspect.
|
62
118
|
def format(arg)
|
63
|
-
|
119
|
+
if arg.is_a?(Exception)
|
64
120
|
"#{arg.class}: #{arg.message}\n\t" <<
|
65
121
|
arg.backtrace.join("\n\t") << "\n"
|
66
122
|
elsif arg.respond_to?(:to_str)
|
@@ -71,14 +127,25 @@ module WEBrick
|
|
71
127
|
end
|
72
128
|
end
|
73
129
|
|
130
|
+
##
|
131
|
+
# A logging class that prepends a timestamp to each message.
|
132
|
+
|
74
133
|
class Log < BasicLog
|
75
|
-
|
134
|
+
# Format of the timestamp which is applied to each logged line. The
|
135
|
+
# default is <tt>"[%Y-%m-%d %H:%M:%S]"</tt>
|
136
|
+
attr_accessor :time_format
|
76
137
|
|
138
|
+
##
|
139
|
+
# Same as BasicLog#initialize
|
140
|
+
#
|
141
|
+
# You can set the timestamp format through #time_format
|
77
142
|
def initialize(log_file=nil, level=nil)
|
78
143
|
super(log_file, level)
|
79
144
|
@time_format = "[%Y-%m-%d %H:%M:%S]"
|
80
145
|
end
|
81
146
|
|
147
|
+
##
|
148
|
+
# Same as BasicLog#log
|
82
149
|
def log(level, data)
|
83
150
|
tmp = Time.now.strftime(@time_format)
|
84
151
|
tmp << " " << data
|
data/lib/webrick/server.rb
CHANGED
@@ -10,21 +10,38 @@
|
|
10
10
|
|
11
11
|
require 'thread'
|
12
12
|
require 'socket'
|
13
|
-
require 'timeout'
|
14
13
|
require 'webrick/config'
|
15
14
|
require 'webrick/log'
|
16
15
|
|
17
16
|
module WEBrick
|
18
17
|
|
18
|
+
##
|
19
|
+
# Server error exception
|
20
|
+
|
19
21
|
class ServerError < StandardError; end
|
20
22
|
|
23
|
+
##
|
24
|
+
# Base server class
|
25
|
+
|
21
26
|
class SimpleServer
|
27
|
+
|
28
|
+
##
|
29
|
+
# A SimpleServer only yields when you start it
|
30
|
+
|
22
31
|
def SimpleServer.start
|
23
32
|
yield
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
36
|
+
##
|
37
|
+
# A generic module for daemonizing a process
|
38
|
+
|
27
39
|
class Daemon
|
40
|
+
|
41
|
+
##
|
42
|
+
# Performs the standard operations for daemonizing a process. Runs a
|
43
|
+
# block, if given.
|
44
|
+
|
28
45
|
def Daemon.start
|
29
46
|
exit!(0) if fork
|
30
47
|
Process::setsid
|
@@ -38,8 +55,41 @@ module WEBrick
|
|
38
55
|
end
|
39
56
|
end
|
40
57
|
|
58
|
+
##
|
59
|
+
# Base TCP server class. You must subclass GenericServer and provide a #run
|
60
|
+
# method.
|
61
|
+
|
41
62
|
class GenericServer
|
42
|
-
|
63
|
+
|
64
|
+
##
|
65
|
+
# The server status. One of :Stop, :Running or :Shutdown
|
66
|
+
|
67
|
+
attr_reader :status
|
68
|
+
|
69
|
+
##
|
70
|
+
# The server configuration
|
71
|
+
|
72
|
+
attr_reader :config
|
73
|
+
|
74
|
+
##
|
75
|
+
# The server logger. This is independent from the HTTP access log.
|
76
|
+
|
77
|
+
attr_reader :logger
|
78
|
+
|
79
|
+
##
|
80
|
+
# Tokens control the number of outstanding clients. The
|
81
|
+
# <code>:MaxClients</code> configuration sets this.
|
82
|
+
|
83
|
+
attr_reader :tokens
|
84
|
+
|
85
|
+
##
|
86
|
+
# Sockets listening for connections.
|
87
|
+
|
88
|
+
attr_reader :listeners
|
89
|
+
|
90
|
+
##
|
91
|
+
# Creates a new generic server from +config+. The default configuration
|
92
|
+
# comes from +default+.
|
43
93
|
|
44
94
|
def initialize(config={}, default=Config::General)
|
45
95
|
@config = default.dup.update(config)
|
@@ -67,14 +117,42 @@ module WEBrick
|
|
67
117
|
end
|
68
118
|
end
|
69
119
|
|
120
|
+
##
|
121
|
+
# Retrieves +key+ from the configuration
|
122
|
+
|
70
123
|
def [](key)
|
71
124
|
@config[key]
|
72
125
|
end
|
73
126
|
|
127
|
+
##
|
128
|
+
# Adds listeners from +address+ and +port+ to the server. See
|
129
|
+
# WEBrick::Utils::create_listeners for details.
|
130
|
+
|
74
131
|
def listen(address, port)
|
75
132
|
@listeners += Utils::create_listeners(address, port, @logger)
|
76
133
|
end
|
77
134
|
|
135
|
+
##
|
136
|
+
# Starts the server and runs the +block+ for each connection. This method
|
137
|
+
# does not return until the server is stopped from a signal handler or
|
138
|
+
# another thread using #stop or #shutdown.
|
139
|
+
#
|
140
|
+
# If the block raises a subclass of StandardError the exception is logged
|
141
|
+
# and ignored. If an IOError or Errno::EBADF exception is raised the
|
142
|
+
# exception is ignored. If an Exception subclass is raised the exception
|
143
|
+
# is logged and re-raised which stops the server.
|
144
|
+
#
|
145
|
+
# To completely shut down a server call #shutdown from ensure:
|
146
|
+
#
|
147
|
+
# server = WEBrick::GenericServer.new
|
148
|
+
# # or WEBrick::HTTPServer.new
|
149
|
+
#
|
150
|
+
# begin
|
151
|
+
# server.start
|
152
|
+
# ensure
|
153
|
+
# server.shutdown
|
154
|
+
# end
|
155
|
+
|
78
156
|
def start(&block)
|
79
157
|
raise ServerError, "already started." if @status != :Stop
|
80
158
|
server_type = @config[:ServerType] || SimpleServer
|
@@ -86,43 +164,58 @@ module WEBrick
|
|
86
164
|
|
87
165
|
thgroup = ThreadGroup.new
|
88
166
|
@status = :Running
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
svrs
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
167
|
+
begin
|
168
|
+
while @status == :Running
|
169
|
+
begin
|
170
|
+
if svrs = IO.select(@listeners, nil, nil, 2.0)
|
171
|
+
svrs[0].each{|svr|
|
172
|
+
@tokens.pop # blocks while no token is there.
|
173
|
+
if sock = accept_client(svr)
|
174
|
+
sock.do_not_reverse_lookup = config[:DoNotReverseLookup]
|
175
|
+
th = start_thread(sock, &block)
|
176
|
+
th[:WEBrickThread] = true
|
177
|
+
thgroup.add(th)
|
178
|
+
else
|
179
|
+
@tokens.push(nil)
|
180
|
+
end
|
181
|
+
}
|
182
|
+
end
|
183
|
+
rescue Errno::EBADF, IOError => ex
|
184
|
+
# if the listening socket was closed in GenericServer#shutdown,
|
185
|
+
# IO::select raise it.
|
186
|
+
rescue StandardError => ex
|
187
|
+
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
188
|
+
@logger.error msg
|
189
|
+
rescue Exception => ex
|
190
|
+
@logger.fatal ex
|
191
|
+
raise
|
102
192
|
end
|
103
|
-
rescue Errno::EBADF, IOError => ex
|
104
|
-
# if the listening socket was closed in GenericServer#shutdown,
|
105
|
-
# IO::select raise it.
|
106
|
-
rescue Exception => ex
|
107
|
-
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
108
|
-
@logger.error msg
|
109
193
|
end
|
110
|
-
end
|
111
194
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
195
|
+
ensure
|
196
|
+
@status = :Shutdown
|
197
|
+
@logger.info "going to shutdown ..."
|
198
|
+
thgroup.list.each{|th| th.join if th[:WEBrickThread] }
|
199
|
+
call_callback(:StopCallback)
|
200
|
+
@logger.info "#{self.class}#start done."
|
201
|
+
@status = :Stop
|
202
|
+
end
|
117
203
|
}
|
118
204
|
end
|
119
205
|
|
206
|
+
##
|
207
|
+
# Stops the server from accepting new connections.
|
208
|
+
|
120
209
|
def stop
|
121
210
|
if @status == :Running
|
122
211
|
@status = :Shutdown
|
123
212
|
end
|
124
213
|
end
|
125
214
|
|
215
|
+
##
|
216
|
+
# Shuts down the server and all listening sockets. New listeners must be
|
217
|
+
# provided to restart the server.
|
218
|
+
|
126
219
|
def shutdown
|
127
220
|
stop
|
128
221
|
@listeners.each{|s|
|
@@ -130,17 +223,38 @@ module WEBrick
|
|
130
223
|
addr = s.addr
|
131
224
|
@logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
|
132
225
|
end
|
133
|
-
|
226
|
+
begin
|
227
|
+
s.shutdown
|
228
|
+
rescue Errno::ENOTCONN
|
229
|
+
# when `Errno::ENOTCONN: Socket is not connected' on some platforms,
|
230
|
+
# call #close instead of #shutdown.
|
231
|
+
# (ignore @config[:ShutdownSocketWithoutClose])
|
232
|
+
s.close
|
233
|
+
else
|
234
|
+
unless @config[:ShutdownSocketWithoutClose]
|
235
|
+
s.close
|
236
|
+
end
|
237
|
+
end
|
134
238
|
}
|
135
239
|
@listeners.clear
|
136
240
|
end
|
137
241
|
|
242
|
+
##
|
243
|
+
# You must subclass GenericServer and implement \#run which accepts a TCP
|
244
|
+
# client socket
|
245
|
+
|
138
246
|
def run(sock)
|
139
247
|
@logger.fatal "run() must be provided by user."
|
140
248
|
end
|
141
249
|
|
142
250
|
private
|
143
251
|
|
252
|
+
# :stopdoc:
|
253
|
+
|
254
|
+
##
|
255
|
+
# Accepts a TCP client socket from the TCP server socket +svr+ and returns
|
256
|
+
# the client socket.
|
257
|
+
|
144
258
|
def accept_client(svr)
|
145
259
|
sock = nil
|
146
260
|
begin
|
@@ -148,16 +262,24 @@ module WEBrick
|
|
148
262
|
sock.sync = true
|
149
263
|
Utils::set_non_blocking(sock)
|
150
264
|
Utils::set_close_on_exec(sock)
|
151
|
-
rescue Errno::ECONNRESET, Errno::ECONNABORTED,
|
152
|
-
|
153
|
-
|
154
|
-
rescue Exception => ex
|
265
|
+
rescue Errno::ECONNRESET, Errno::ECONNABORTED,
|
266
|
+
Errno::EPROTO, Errno::EINVAL => ex
|
267
|
+
rescue StandardError => ex
|
155
268
|
msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
|
156
269
|
@logger.error msg
|
157
270
|
end
|
158
271
|
return sock
|
159
272
|
end
|
160
273
|
|
274
|
+
##
|
275
|
+
# Starts a server thread for the client socket +sock+ that runs the given
|
276
|
+
# +block+.
|
277
|
+
#
|
278
|
+
# Sets the socket to the <code>:WEBrickSocket</code> thread local variable
|
279
|
+
# in the thread.
|
280
|
+
#
|
281
|
+
# If any errors occur in the block they are logged and handled.
|
282
|
+
|
161
283
|
def start_thread(sock, &block)
|
162
284
|
Thread.start{
|
163
285
|
begin
|
@@ -186,11 +308,14 @@ module WEBrick
|
|
186
308
|
else
|
187
309
|
@logger.debug "close: <address unknown>"
|
188
310
|
end
|
189
|
-
sock.close
|
311
|
+
sock.close unless sock.closed?
|
190
312
|
end
|
191
313
|
}
|
192
314
|
end
|
193
315
|
|
316
|
+
##
|
317
|
+
# Calls the callback +callback_name+ from the configuration with +args+
|
318
|
+
|
194
319
|
def call_callback(callback_name, *args)
|
195
320
|
if cb = @config[callback_name]
|
196
321
|
cb.call(*args)
|