An HTTP Server
Creates a new HTTP server according to config
An HTTP server uses the following attributes:
An array of access logs. See WEBrick::AccessLog
Local address for the server to bind to
Root path to serve files from
Options for the default HTTPServlet::FileHandler
The HTTP version of this server
Port to listen on
Called with a request and response before each request is serviced.
Maximum time to wait between requests
Array of alternate names for this server for virtual hosting
Name for this server for virtual hosting
# File webrick/httpserver.rb, line 44
def initialize(config={}, default=Config::HTTP)
super(config, default)
@http_version = HTTPVersion::convert(@config[:HTTPVersion])
@mount_tab = MountTable.new
if @config[:DocumentRoot]
mount("/", HTTPServlet::FileHandler, @config[:DocumentRoot],
@config[:DocumentRootOptions])
end
unless @config[:AccessLog]
@config[:AccessLog] = [
[ $stderr, AccessLog::COMMON_LOG_FORMAT ],
[ $stderr, AccessLog::REFERER_LOG_FORMAT ]
]
end
@virtual_hosts = Array.new
end
# File webrick/httpserver.rb, line 210
def access_log(config, req, res)
param = AccessLog::setup_params(config, req, res)
@config[:AccessLog].each{|logger, fmt|
logger << AccessLog::format(fmt+"\n", param)
}
end
# File webrick/httpserver.rb, line 141
def do_OPTIONS(req, res)
res["allow"] = "GET,HEAD,POST,OPTIONS"
end
Finds the appropriate virtual host to handle req
# File webrick/httpserver.rb, line 201
def lookup_server(req)
@virtual_hosts.find{|s|
(s[:BindAddress].nil? || req.addr[3] == s[:BindAddress]) &&
(s[:Port].nil? || req.port == s[:Port]) &&
((s[:ServerName].nil? || req.host == s[:ServerName]) ||
(!s[:ServerAlias].nil? && s[:ServerAlias].find{|h| h === req.host}))
}
end
Mounts servlet on dir passing
options to the servlet at creation time
# File webrick/httpserver.rb, line 149
def mount(dir, servlet, *options)
@logger.debug(sprintf("%s is mounted on %s.", servlet.inspect, dir))
@mount_tab[dir] = [ servlet, options ]
end
Mounts proc or block on dir and
calls it with a WEBrick::HTTPRequest and WEBrick::HTTPResponse
# File webrick/httpserver.rb, line 158
def mount_proc(dir, proc=nil, &block)
proc ||= block
raise HTTPServerError, "must pass a proc or block" unless proc
mount(dir, HTTPServlet::ProcHandler.new(proc))
end
Processes requests on sock
# File webrick/httpserver.rb, line 67
def run(sock)
while true
res = HTTPResponse.new(@config)
req = HTTPRequest.new(@config)
server = self
begin
timeout = @config[:RequestTimeout]
while timeout > 0
break if IO.select([sock], nil, nil, 0.5)
timeout = 0 if @status != :Running
timeout -= 0.5
end
raise HTTPStatus::EOFError if timeout <= 0
raise HTTPStatus::EOFError if sock.eof?
req.parse(sock)
res.request_method = req.request_method
res.request_uri = req.request_uri
res.request_http_version = req.http_version
res.keep_alive = req.keep_alive?
server = lookup_server(req) || self
if callback = server[:RequestCallback]
callback.call(req, res)
elsif callback = server[:RequestHandler]
msg = ":RequestHandler is deprecated, please use :RequestCallback"
@logger.warn(msg)
callback.call(req, res)
end
server.service(req, res)
rescue HTTPStatus::EOFError, HTTPStatus::RequestTimeout => ex
res.set_error(ex)
rescue HTTPStatus::Error => ex
@logger.error(ex.message)
res.set_error(ex)
rescue HTTPStatus::Status => ex
res.status = ex.code
rescue StandardError => ex
@logger.error(ex)
res.set_error(ex, true)
ensure
if req.request_line
if req.keep_alive? && res.keep_alive?
req.fixup()
end
res.send_response(sock)
server.access_log(@config, req, res)
end
end
break if @http_version < "1.1"
break unless req.keep_alive?
break unless res.keep_alive?
end
end
Finds a servlet for path
# File webrick/httpserver.rb, line 176
def search_servlet(path)
script_name, path_info = @mount_tab.scan(path)
servlet, options = @mount_tab[script_name]
if servlet
[ servlet, options, script_name, path_info ]
end
end
Services req and fills in res
# File webrick/httpserver.rb, line 123
def service(req, res)
if req.unparsed_uri == "*"
if req.request_method == "OPTIONS"
do_OPTIONS(req, res)
raise HTTPStatus::OK
end
raise HTTPStatus::NotFound, "`#{req.unparsed_uri}' not found."
end
servlet, options, script_name, path_info = search_servlet(req.path)
raise HTTPStatus::NotFound, "`#{req.path}' not found." unless servlet
req.script_name = script_name
req.path_info = path_info
si = servlet.get_instance(self, *options)
@logger.debug(format("%s is invoked.", si.class.name))
si.service(req, res)
end
Unmounts dir
# File webrick/httpserver.rb, line 167
def unmount(dir)
@logger.debug(sprintf("unmount %s.", dir))
@mount_tab.delete(dir)
end
Adds server as a virtual host.
# File webrick/httpserver.rb, line 187
def virtual_host(server)
@virtual_hosts << server
@virtual_hosts = @virtual_hosts.sort_by{|s|
num = 0
num -= 4 if s[:BindAddress]
num -= 2 if s[:Port]
num -= 1 if s[:ServerName]
num
}
end
Commenting is here to help enhance the documentation. For example, sample code, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.