summaryrefslogtreecommitdiff
path: root/lib/webrick/httpserver.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/webrick/httpserver.rb')
-rw-r--r--lib/webrick/httpserver.rb124
1 files changed, 104 insertions, 20 deletions
diff --git a/lib/webrick/httpserver.rb b/lib/webrick/httpserver.rb
index 9edb0018f8..e85d059319 100644
--- a/lib/webrick/httpserver.rb
+++ b/lib/webrick/httpserver.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: false
#
# httpserver.rb -- HTTPServer Class
#
@@ -8,20 +9,42 @@
#
# $IPR: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $
-require 'webrick/server'
-require 'webrick/httputils'
-require 'webrick/httpstatus'
-require 'webrick/httprequest'
-require 'webrick/httpresponse'
-require 'webrick/httpservlet'
-require 'webrick/accesslog'
+require 'io/wait'
+require_relative 'server'
+require_relative 'httputils'
+require_relative 'httpstatus'
+require_relative 'httprequest'
+require_relative 'httpresponse'
+require_relative 'httpservlet'
+require_relative 'accesslog'
module WEBrick
class HTTPServerError < ServerError; end
+ ##
+ # An HTTP Server
+
class HTTPServer < ::WEBrick::GenericServer
+ ##
+ # Creates a new HTTP server according to +config+
+ #
+ # An HTTP server uses the following attributes:
+ #
+ # :AccessLog:: An array of access logs. See WEBrick::AccessLog
+ # :BindAddress:: Local address for the server to bind to
+ # :DocumentRoot:: Root path to serve files from
+ # :DocumentRootOptions:: Options for the default HTTPServlet::FileHandler
+ # :HTTPVersion:: The HTTP version of this server
+ # :Port:: Port to listen on
+ # :RequestCallback:: Called with a request and response before each
+ # request is serviced.
+ # :RequestTimeout:: Maximum time to wait between requests
+ # :ServerAlias:: Array of alternate names for this server for virtual
+ # hosting
+ # :ServerName:: Name for this server for virtual hosting
+
def initialize(config={}, default=Config::HTTP)
- super
+ super(config, default)
@http_version = HTTPVersion::convert(@config[:HTTPVersion])
@mount_tab = MountTable.new
@@ -36,30 +59,38 @@ module WEBrick
[ $stderr, AccessLog::REFERER_LOG_FORMAT ]
]
end
-
+
@virtual_hosts = Array.new
end
+ ##
+ # Processes requests on +sock+
+
def run(sock)
- while true
- res = HTTPResponse.new(@config)
- req = HTTPRequest.new(@config)
+ while true
+ req = create_request(@config)
+ res = create_response(@config)
server = self
begin
timeout = @config[:RequestTimeout]
while timeout > 0
- break if IO.select([sock], nil, nil, 0.5)
- timeout = 0 if @status != :Running
+ break if sock.to_io.wait_readable(0.5)
+ break if @status != :Running
timeout -= 0.5
end
- raise HTTPStatus::EOFError if timeout <= 0 || sock.eof?
+ raise HTTPStatus::EOFError if timeout <= 0 || @status != :Running
+ 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] || server[:RequestHandler]
+ 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)
@@ -75,7 +106,9 @@ module WEBrick
res.set_error(ex, true)
ensure
if req.request_line
- req.fixup()
+ if req.keep_alive? && res.keep_alive?
+ req.fixup()
+ end
res.send_response(sock)
server.access_log(@config, req, res)
end
@@ -86,6 +119,9 @@ module WEBrick
end
end
+ ##
+ # Services +req+ and fills in +res+
+
def service(req, res)
if req.unparsed_uri == "*"
if req.request_method == "OPTIONS"
@@ -104,27 +140,45 @@ module WEBrick
si.service(req, res)
end
+ ##
+ # The default OPTIONS request handler says GET, HEAD, POST and OPTIONS
+ # requests are allowed.
+
def do_OPTIONS(req, res)
res["allow"] = "GET,HEAD,POST,OPTIONS"
end
+ ##
+ # Mounts +servlet+ on +dir+ passing +options+ to the servlet at creation
+ # time
+
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
+
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
+ ##
+ # Unmounts +dir+
+
def unmount(dir)
@logger.debug(sprintf("unmount %s.", dir))
@mount_tab.delete(dir)
end
alias umount unmount
+ ##
+ # Finds a servlet for +path+
+
def search_servlet(path)
script_name, path_info = @mount_tab.scan(path)
servlet, options = @mount_tab[script_name]
@@ -133,6 +187,9 @@ module WEBrick
end
end
+ ##
+ # Adds +server+ as a virtual host.
+
def virtual_host(server)
@virtual_hosts << server
@virtual_hosts = @virtual_hosts.sort_by{|s|
@@ -144,6 +201,9 @@ module WEBrick
}
end
+ ##
+ # Finds the appropriate virtual host to handle +req+
+
def lookup_server(req)
@virtual_hosts.find{|s|
(s[:BindAddress].nil? || req.addr[3] == s[:BindAddress]) &&
@@ -153,6 +213,10 @@ module WEBrick
}
end
+ ##
+ # Logs +req+ and +res+ in the access logs. +config+ is used for the
+ # server name.
+
def access_log(config, req, res)
param = AccessLog::setup_params(config, req, res)
@config[:AccessLog].each{|logger, fmt|
@@ -160,7 +224,27 @@ module WEBrick
}
end
- class MountTable
+ ##
+ # Creates the HTTPRequest used when handling the HTTP
+ # request. Can be overridden by subclasses.
+ def create_request(with_webrick_config)
+ HTTPRequest.new(with_webrick_config)
+ end
+
+ ##
+ # Creates the HTTPResponse used when handling the HTTP
+ # request. Can be overridden by subclasses.
+ def create_response(with_webrick_config)
+ HTTPResponse.new(with_webrick_config)
+ end
+
+ ##
+ # Mount table for the path a servlet is mounted on in the directory space
+ # of the server. Users of WEBrick can only access this indirectly via
+ # WEBrick::HTTPServer#mount, WEBrick::HTTPServer#unmount and
+ # WEBrick::HTTPServer#search_servlet
+
+ class MountTable # :nodoc:
def initialize
@tab = Hash.new
compile
@@ -197,12 +281,12 @@ module WEBrick
k.sort!
k.reverse!
k.collect!{|path| Regexp.escape(path) }
- @scanner = Regexp.new("^(" + k.join("|") +")(?=/|$)")
+ @scanner = Regexp.new("\\A(" + k.join("|") +")(?=/|\\z)")
end
def normalize(dir)
ret = dir ? dir.dup : ""
- ret.sub!(%r|/+$|, "")
+ ret.sub!(%r|/+\z|, "")
ret
end
end