aboutsummaryrefslogtreecommitdiffstats
path: root/lib/webrick
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-01-26 01:12:54 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-01-26 01:12:54 +0000
commit28afe277a8e543da0e6353bdacbcad0b69739e06 (patch)
tree1591c370f08ab4db6c888eea99f2936262e137ca /lib/webrick
parent89232d1dd97251b6fc626d4338c49e9e8c4f6535 (diff)
downloadruby-28afe277a8e543da0e6353bdacbcad0b69739e06.tar.gz
* lib/webrick/accesslog.rb: Improved WEBrick documentation.
* lib/webrick/cgi.rb: ditto. * lib/webrick/config.rb: ditto. * lib/webrick/cookie.rb: ditto. * lib/webrick/httpauth/authenticator.rb: ditto. * lib/webrick/httpauth/basicauth.rb: ditto. * lib/webrick/httpauth/digestauth.rb: ditto. * lib/webrick/httpproxy.rb: ditto. * lib/webrick/httprequest.rb: ditto. * lib/webrick/httpresponse.rb: ditto. * lib/webrick/https.rb: ditto. * lib/webrick/httpserver.rb: ditto. * lib/webrick/httpservlet/cgihandler.rb: ditto. * lib/webrick/httpservlet/filehandler.rb: ditto. * lib/webrick/httpservlet/prochandler.rb: ditto. * lib/webrick/httputils.rb: ditto. * lib/webrick/httpversion.rb: ditto. * lib/webrick/log.rb: ditto. * lib/webrick/server.rb: ditto. * lib/webrick/ssl.rb: ditto. * lib/webrick/utils.rb: ditto. * lib/webrick/version.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38945 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/webrick')
-rw-r--r--lib/webrick/accesslog.rb7
-rw-r--r--lib/webrick/cgi.rb52
-rw-r--r--lib/webrick/config.rb32
-rw-r--r--lib/webrick/cookie.rb71
-rw-r--r--lib/webrick/httpauth/authenticator.rb20
-rw-r--r--lib/webrick/httpauth/basicauth.rb2
-rw-r--r--lib/webrick/httpauth/digestauth.rb24
-rw-r--r--lib/webrick/httpproxy.rb14
-rw-r--r--lib/webrick/httprequest.rb146
-rw-r--r--lib/webrick/httpresponse.rb78
-rw-r--r--lib/webrick/https.rb24
-rw-r--r--lib/webrick/httpserver.rb16
-rw-r--r--lib/webrick/httpservlet/cgihandler.rb19
-rw-r--r--lib/webrick/httpservlet/filehandler.rb46
-rw-r--r--lib/webrick/httpservlet/prochandler.rb13
-rw-r--r--lib/webrick/httputils.rb127
-rw-r--r--lib/webrick/httpversion.rb28
-rw-r--r--lib/webrick/log.rb23
-rw-r--r--lib/webrick/server.rb74
-rw-r--r--lib/webrick/ssl.rb72
-rw-r--r--lib/webrick/utils.rb3
-rw-r--r--lib/webrick/version.rb4
22 files changed, 812 insertions, 83 deletions
diff --git a/lib/webrick/accesslog.rb b/lib/webrick/accesslog.rb
index 029b5a4902..0a3c380406 100644
--- a/lib/webrick/accesslog.rb
+++ b/lib/webrick/accesslog.rb
@@ -115,6 +115,10 @@ module WEBrick
params
end
+ ##
+ # Formats +params+ according to +format_string+ which is described in
+ # setup_params.
+
def format(format_string, params)
format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
param, spec = $1, $2
@@ -140,6 +144,9 @@ module WEBrick
}
end
+ ##
+ # Escapes control characters in +data+
+
def escape(data)
if data.tainted?
data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint
diff --git a/lib/webrick/cgi.rb b/lib/webrick/cgi.rb
index 806d050bc9..80f636edc3 100644
--- a/lib/webrick/cgi.rb
+++ b/lib/webrick/cgi.rb
@@ -13,10 +13,44 @@ require "webrick/config"
require "stringio"
module WEBrick
+
+ # A CGI library using WEBrick requests and responses.
+ #
+ # Example:
+ #
+ # class MyCGI < WEBrick::CGI
+ # def do_GET req, res
+ # res.body = 'it worked!'
+ # res.status = 200
+ # end
+ # end
+ #
+ # MyCGI.new.start
+
class CGI
+
+ # The CGI error exception class
+
CGIError = Class.new(StandardError)
- attr_reader :config, :logger
+ ##
+ # The CGI configuration. This is based on WEBrick::Config::HTTP
+
+ attr_reader :config
+
+ ##
+ # The CGI logger
+
+ attr_reader :logger
+
+ ##
+ # Creates a new CGI interface.
+ #
+ # The first argument in +args+ is a configuration hash which would update
+ # WEBrick::Config::HTTP.
+ #
+ # Any remaining arguments are stored in the <code>@options</code> instance
+ # variable for use by a subclass.
def initialize(*args)
if defined?(MOD_RUBY)
@@ -41,10 +75,17 @@ module WEBrick
@options = args
end
+ ##
+ # Reads +key+ from the configuration
+
def [](key)
@config[key]
end
+ ##
+ # Starts the CGI process with the given environment +env+ and standard
+ # input and output +stdin+ and +stdout+.
+
def start(env=ENV, stdin=$stdin, stdout=$stdout)
sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout)
req = HTTPRequest.new(@config)
@@ -108,6 +149,10 @@ module WEBrick
end
end
+ ##
+ # Services the request +req+ which will fill in the response +res+. See
+ # WEBrick::HTTPServlet::AbstractServlet#service for details.
+
def service(req, res)
method_name = "do_" + req.request_method.gsub(/-/, "_")
if respond_to?(method_name)
@@ -118,7 +163,10 @@ module WEBrick
end
end
- class Socket
+ ##
+ # Provides HTTP socket emulation from the CGI environment
+
+ class Socket # :nodoc:
include Enumerable
private
diff --git a/lib/webrick/config.rb b/lib/webrick/config.rb
index 8c6427020d..c347da4be6 100644
--- a/lib/webrick/config.rb
+++ b/lib/webrick/config.rb
@@ -16,7 +16,7 @@ require 'webrick/log'
module WEBrick
module Config
- LIBDIR = File::dirname(__FILE__)
+ LIBDIR = File::dirname(__FILE__) # :nodoc:
# for GenericServer
General = {
@@ -67,6 +67,30 @@ module WEBrick
:Escape8bitURI => false
)
+ ##
+ # Default configuration for WEBrick::HTTPServlet::FileHandler
+ #
+ # :AcceptableLanguages::
+ # Array of languages allowed for accept-language. There is no default
+ # :DirectoryCallback::
+ # Allows preprocessing of directory requests. There is no default
+ # callback.
+ # :FancyIndexing::
+ # If true, show an index for directories. The default is true.
+ # :FileCallback::
+ # Allows preprocessing of file requests. There is no default callback.
+ # :HandlerCallback::
+ # Allows preprocessing of requests. There is no default callback.
+ # :HandlerTable::
+ # Maps file suffixes to file handlers. DefaultFileHandler is used by
+ # default but any servlet can be used.
+ # :NondisclosureName::
+ # Do not show files matching this array of globs. .ht* and *~ are
+ # excluded by default.
+ # :UserDir::
+ # Directory inside ~user to serve content from for /~user requests.
+ # Only works if mounted on /. Disabled by default.
+
FileHandler = {
:NondisclosureName => [".ht*", "*~"],
:FancyIndexing => false,
@@ -78,6 +102,12 @@ module WEBrick
:AcceptableLanguages => [] # ["en", "ja", ... ]
}
+ ##
+ # Default configuration for WEBrick::HTTPAuth::BasicAuth
+ #
+ # :AutoReloadUserDB:: Reload the user database provided by :UserDB
+ # automatically?
+
BasicAuth = {
:AutoReloadUserDB => true,
}
diff --git a/lib/webrick/cookie.rb b/lib/webrick/cookie.rb
index 814e6645a3..3cf8928bb0 100644
--- a/lib/webrick/cookie.rb
+++ b/lib/webrick/cookie.rb
@@ -12,14 +12,56 @@ require 'time'
require 'webrick/httputils'
module WEBrick
+
+ ##
+ # Processes HTTP cookies
+
class Cookie
+ ##
+ # The cookie name
+
attr_reader :name
- attr_accessor :value, :version
- attr_accessor :domain, :path, :secure
- attr_accessor :comment, :max_age
+
+ ##
+ # The cookie value
+
+ attr_accessor :value
+
+ ##
+ # The cookie version
+
+ attr_accessor :version
+
+ ##
+ # The cookie domain
+ attr_accessor :domain
+
+ ##
+ # The cookie path
+
+ attr_accessor :path
+
+ ##
+ # Is this a secure cookie?
+
+ attr_accessor :secure
+
+ ##
+ # The cookie comment
+
+ attr_accessor :comment
+
+ ##
+ # The maximum age of the cookie
+
+ attr_accessor :max_age
+
#attr_accessor :comment_url, :discard, :port
+ ##
+ # Creates a new cookie with the given +name+ and +value+
+
def initialize(name, value)
@name = name
@value = value
@@ -29,14 +71,25 @@ module WEBrick
@expires = @comment_url = @discard = @port = nil
end
+ ##
+ # Sets the cookie expiration to the time +t+. The expiration time may be
+ # a false value to disable expiration or a Time or HTTP format time string
+ # to set the expiration date.
+
def expires=(t)
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
end
+ ##
+ # Retrieves the expiration time as a Time
+
def expires
@expires && Time.parse(@expires)
end
+ ##
+ # The cookie string suitable for use in an HTTP header
+
def to_s
ret = ""
ret << @name << "=" << @value
@@ -50,8 +103,10 @@ module WEBrick
ret
end
- # Cookie::parse()
- # It parses Cookie field sent from the user agent.
+ ##
+ # Parses a Cookie field sent from the user-agent. Returns an array of
+ # cookies.
+
def self.parse(str)
if str
ret = []
@@ -76,6 +131,9 @@ module WEBrick
end
end
+ ##
+ # Parses the cookie in +str+
+
def self.parse_set_cookie(str)
cookie_elem = str.split(/;/)
first_elem = cookie_elem.shift
@@ -101,6 +159,9 @@ module WEBrick
return cookie
end
+ ##
+ # Parses the cookies in +str+
+
def self.parse_set_cookies(str)
return str.split(/,(?=[^;,]*=)|,$/).collect{|c|
parse_set_cookie(c)
diff --git a/lib/webrick/httpauth/authenticator.rb b/lib/webrick/httpauth/authenticator.rb
index 9b9beeceba..f6d4ab844f 100644
--- a/lib/webrick/httpauth/authenticator.rb
+++ b/lib/webrick/httpauth/authenticator.rb
@@ -16,10 +16,10 @@ module WEBrick
module Authenticator
- RequestField = "Authorization"
- ResponseField = "WWW-Authenticate"
- ResponseInfoField = "Authentication-Info"
- AuthException = HTTPStatus::Unauthorized
+ RequestField = "Authorization" # :nodoc:
+ ResponseField = "WWW-Authenticate" # :nodoc:
+ ResponseInfoField = "Authentication-Info" # :nodoc:
+ AuthException = HTTPStatus::Unauthorized # :nodoc:
##
# Method of authentication, must be overridden by the including class
@@ -43,6 +43,8 @@ module WEBrick
private
+ # :stopdoc:
+
##
# Initializes the authenticator from +config+
@@ -96,6 +98,8 @@ module WEBrick
log(:info, fmt, *args)
end
end
+
+ # :startdoc:
end
##
@@ -103,10 +107,10 @@ module WEBrick
# authentication schemes for proxies.
module ProxyAuthenticator
- RequestField = "Proxy-Authorization"
- ResponseField = "Proxy-Authenticate"
- InfoField = "Proxy-Authentication-Info"
- AuthException = HTTPStatus::ProxyAuthenticationRequired
+ RequestField = "Proxy-Authorization" # :nodoc:
+ ResponseField = "Proxy-Authenticate" # :nodoc:
+ InfoField = "Proxy-Authentication-Info" # :nodoc:
+ AuthException = HTTPStatus::ProxyAuthenticationRequired # :nodoc:
end
end
end
diff --git a/lib/webrick/httpauth/basicauth.rb b/lib/webrick/httpauth/basicauth.rb
index 4c51e53199..3ff20b56d2 100644
--- a/lib/webrick/httpauth/basicauth.rb
+++ b/lib/webrick/httpauth/basicauth.rb
@@ -34,7 +34,7 @@ module WEBrick
class BasicAuth
include Authenticator
- AuthScheme = "Basic"
+ AuthScheme = "Basic" # :nodoc:
##
# Used by UserDB to create a basic password entry
diff --git a/lib/webrick/httpauth/digestauth.rb b/lib/webrick/httpauth/digestauth.rb
index 4e47fe163f..78ad45b233 100644
--- a/lib/webrick/httpauth/digestauth.rb
+++ b/lib/webrick/httpauth/digestauth.rb
@@ -45,9 +45,22 @@ module WEBrick
class DigestAuth
include Authenticator
- AuthScheme = "Digest"
- OpaqueInfo = Struct.new(:time, :nonce, :nc)
- attr_reader :algorithm, :qop
+ AuthScheme = "Digest" # :nodoc:
+
+ ##
+ # Struct containing the opaque portion of the digest authentication
+
+ OpaqueInfo = Struct.new(:time, :nonce, :nc) # :nodoc:
+
+ ##
+ # Digest authentication algorithm
+
+ attr_reader :algorithm
+
+ ##
+ # Quality of protection. RFC 2617 defines "auth" and "auth-int"
+
+ attr_reader :qop
##
# Used by UserDB to create a digest password entry
@@ -142,6 +155,8 @@ module WEBrick
private
+ # :stopdoc:
+
MustParams = ['username','realm','nonce','uri','response']
MustParamsAuth = ['cnonce','nc']
@@ -375,6 +390,7 @@ module WEBrick
@h.hexdigest(args.join(":"))
end
+ # :startdoc:
end
##
@@ -384,7 +400,7 @@ module WEBrick
include ProxyAuthenticator
private
- def check_uri(req, auth_req)
+ def check_uri(req, auth_req) # :nodoc:
return true
end
end
diff --git a/lib/webrick/httpproxy.rb b/lib/webrick/httpproxy.rb
index e7226a0a6c..3ad573d5d9 100644
--- a/lib/webrick/httpproxy.rb
+++ b/lib/webrick/httpproxy.rb
@@ -15,16 +15,17 @@ require "net/http"
Net::HTTP::version_1_2 if RUBY_VERSION < "1.7"
module WEBrick
- NullReader = Object.new
- class << NullReader
+
+ NullReader = Object.new # :nodoc:
+ class << NullReader # :nodoc:
def read(*args)
nil
end
alias gets read
end
- FakeProxyURI = Object.new
- class << FakeProxyURI
+ FakeProxyURI = Object.new # :nodoc:
+ class << FakeProxyURI # :nodoc:
def method_missing(meth, *args)
if %w(scheme host port path query userinfo).member?(meth.to_s)
return nil
@@ -33,6 +34,8 @@ module WEBrick
end
end
+ # :startdoc:
+
##
# An HTTP Proxy server which proxies GET, HEAD and POST requests.
#
@@ -85,6 +88,7 @@ module WEBrick
@via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
end
+ # :stopdoc:
def service(req, res)
if req.request_method == "CONNECT"
do_CONNECT(req, res)
@@ -329,5 +333,7 @@ module WEBrick
set_via(res)
res.body = response.body
end
+
+ # :stopdoc:
end
end
diff --git a/lib/webrick/httprequest.rb b/lib/webrick/httprequest.rb
index 050b5ed45b..10b9e6131e 100644
--- a/lib/webrick/httprequest.rb
+++ b/lib/webrick/httprequest.rb
@@ -17,31 +17,137 @@ require 'webrick/cookie'
module WEBrick
##
- # An HTTP request.
+ # An HTTP request. This is consumed by service and do_* methods in
+ # WEBrick servlets
+
class HTTPRequest
- BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ]
+ BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
# :section: Request line
+
+ ##
+ # The complete request line such as:
+ #
+ # GET / HTTP/1.1
+
attr_reader :request_line
- attr_reader :request_method, :unparsed_uri, :http_version
+
+ ##
+ # The request method, GET, POST, PUT, etc.
+
+ attr_reader :request_method
+
+ ##
+ # The unparsed URI of the request
+
+ attr_reader :unparsed_uri
+
+ ##
+ # The HTTP version of the request
+
+ attr_reader :http_version
# :section: Request-URI
- attr_reader :request_uri, :path
- attr_accessor :script_name, :path_info, :query_string
+
+ ##
+ # The parsed URI of the request
+
+ attr_reader :request_uri
+
+ ##
+ # The request path
+
+ attr_reader :path
+
+ ##
+ # The script name (CGI variable)
+
+ attr_accessor :script_name
+
+ ##
+ # The path info (CGI variable)
+
+ attr_accessor :path_info
+
+ ##
+ # The query from the URI of the request
+
+ attr_accessor :query_string
# :section: Header and entity body
- attr_reader :raw_header, :header, :cookies
- attr_reader :accept, :accept_charset
- attr_reader :accept_encoding, :accept_language
+
+ ##
+ # The raw header of the request
+
+ attr_reader :raw_header
+
+ ##
+ # The parsed header of the request
+
+ attr_reader :header
+
+ ##
+ # The parsed request cookies
+
+ attr_reader :cookies
+
+ ##
+ # The Accept header value
+
+ attr_reader :accept
+
+ ##
+ # The Accept-Charset header value
+
+ attr_reader :accept_charset
+
+ ##
+ # The Accept-Encoding header value
+
+ attr_reader :accept_encoding
+
+ ##
+ # The Accept-Language header value
+
+ attr_reader :accept_language
# :section:
+
+ ##
+ # The remote user (CGI variable)
+
attr_accessor :user
- attr_reader :addr, :peeraddr
+
+ ##
+ # The socket address of the server
+
+ attr_reader :addr
+
+ ##
+ # The socket address of the client
+
+ attr_reader :peeraddr
+
+ ##
+ # Hash of request attributes
+
attr_reader :attributes
+
+ ##
+ # Is this a keep-alive connection?
+
attr_reader :keep_alive
+
+ ##
+ # The local time this request was received
+
attr_reader :request_time
+ ##
+ # Creates a new HTTP request. WEBrick::Config::HTTP is the default
+ # configuration.
+
def initialize(config)
@config = config
@buffer_size = @config[:InputBufferSize]
@@ -78,6 +184,10 @@ module WEBrick
@forwarded_server = @forwarded_for = nil
end
+ ##
+ # Parses a request from +socket+. This is called internally by
+ # WEBrick::HTTPServer.
+
def parse(socket=nil)
@socket = socket
begin
@@ -126,16 +236,21 @@ module WEBrick
end
end
+ ##
# Generate HTTP/1.1 100 continue response if the client expects it,
# otherwise does nothing.
- def continue
+
+ def continue # :nodoc:
if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
@socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
@header.delete('expect')
end
end
- def body(&block)
+ ##
+ # Returns the request body.
+
+ def body(&block) # :yields: body_chunk
block ||= Proc.new{|chunk| @body << chunk }
read_body(@socket, block)
@body.empty? ? nil : @body
@@ -237,7 +352,10 @@ module WEBrick
ret
end
- def fixup()
+ ##
+ # Consumes any remaining body and updates keep-alive status
+
+ def fixup() # :nodoc:
begin
body{|chunk| } # read remaining body
rescue HTTPStatus::Error => ex
@@ -290,6 +408,8 @@ module WEBrick
private
+ # :stopdoc:
+
MAX_URI_LENGTH = 2083 # :nodoc:
def read_request_line(socket)
@@ -457,5 +577,7 @@ module WEBrick
@forwarded_for = addrs.first
end
end
+
+ # :startdoc:
end
end
diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb
index 5adbc82173..8e3eb39a31 100644
--- a/lib/webrick/httpresponse.rb
+++ b/lib/webrick/httpresponse.rb
@@ -16,11 +16,34 @@ require 'webrick/httpstatus'
module WEBrick
##
- # An HTTP response.
+ # An HTTP response. This is filled in by the service or do_* methods of a
+ # WEBrick HTTP Servlet.
class HTTPResponse
- attr_reader :http_version, :status, :header
+
+ ##
+ # HTTP Response version
+
+ attr_reader :http_version
+
+ ##
+ # Response status code (200)
+
+ attr_reader :status
+
+ ##
+ # Response header
+
+ attr_reader :header
+
+ ##
+ # Response cookies
+
attr_reader :cookies
+
+ ##
+ # Response reason phrase ("OK")
+
attr_accessor :reason_phrase
##
@@ -28,13 +51,45 @@ module WEBrick
attr_accessor :body
- attr_accessor :request_method, :request_uri, :request_http_version
+ ##
+ # Request method for this response
+
+ attr_accessor :request_method
+
+ ##
+ # Request URI for this response
+
+ attr_accessor :request_uri
+
+ ##
+ # Request HTTP version for this response
+
+ attr_accessor :request_http_version
+
+ ##
+ # Filename of the static file in this response. Only used by the
+ # FileHandler servlet.
+
attr_accessor :filename
+
+ ##
+ # Is this a keep-alive response?
+
attr_accessor :keep_alive
- attr_reader :config, :sent_size
##
- # Creates a new HTTP response object
+ # Configuration for this response
+
+ attr_reader :config
+
+ ##
+ # Bytes sent in this response
+
+ attr_reader :sent_size
+
+ ##
+ # Creates a new HTTP response object. WEBrick::Config::HTTP is the
+ # default configuration.
def initialize(config)
@config = config
@@ -145,7 +200,7 @@ module WEBrick
##
# Sends the response on +socket+
- def send_response(socket)
+ def send_response(socket) # :nodoc:
begin
setup_header()
send_header(socket)
@@ -162,7 +217,7 @@ module WEBrick
##
# Sets up the headers for sending
- def setup_header()
+ def setup_header() # :nodoc:
@reason_phrase ||= HTTPStatus::reason_phrase(@status)
@header['server'] ||= @config[:ServerSoftware]
@header['date'] ||= Time.now.httpdate
@@ -225,7 +280,7 @@ module WEBrick
##
# Sends the headers on +socket+
- def send_header(socket)
+ def send_header(socket) # :nodoc:
if @http_version.major > 0
data = status_line()
@header.each{|key, value|
@@ -243,7 +298,7 @@ module WEBrick
##
# Sends the body on +socket+
- def send_body(socket)
+ def send_body(socket) # :nodoc:
case @body
when IO then send_body_io(socket)
else send_body_string(socket)
@@ -325,6 +380,8 @@ module WEBrick
private
+ # :stopdoc:
+
def send_body_io(socket)
begin
if @request_method == "HEAD"
@@ -400,5 +457,8 @@ module WEBrick
def _write_data(socket, data)
socket << data
end
+
+ # :startdoc:
end
+
end
diff --git a/lib/webrick/https.rb b/lib/webrick/https.rb
index abb428451f..9194f9411c 100644
--- a/lib/webrick/https.rb
+++ b/lib/webrick/https.rb
@@ -15,8 +15,28 @@ module WEBrick
HTTP.update(SSL)
end
+ ##
+ #--
+ # Adds SSL functionality to WEBrick::HTTPRequest
+
class HTTPRequest
- attr_reader :cipher, :server_cert, :client_cert
+
+ ##
+ # HTTP request SSL cipher
+
+ attr_reader :cipher
+
+ ##
+ # HTTP request server certificate
+
+ attr_reader :server_cert
+
+ ##
+ # HTTP request client certificate
+
+ attr_reader :client_cert
+
+ # :stopdoc:
alias orig_parse parse
@@ -60,5 +80,7 @@ module WEBrick
end
meta
end
+
+ # :startdoc:
end
end
diff --git a/lib/webrick/httpserver.rb b/lib/webrick/httpserver.rb
index ddf1ac7404..7a7b931dad 100644
--- a/lib/webrick/httpserver.rb
+++ b/lib/webrick/httpserver.rb
@@ -138,6 +138,10 @@ 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
@@ -207,6 +211,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|
@@ -214,7 +222,13 @@ module WEBrick
}
end
- class MountTable
+ ##
+ # 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
diff --git a/lib/webrick/httpservlet/cgihandler.rb b/lib/webrick/httpservlet/cgihandler.rb
index 1976ae6948..7c012ca64b 100644
--- a/lib/webrick/httpservlet/cgihandler.rb
+++ b/lib/webrick/httpservlet/cgihandler.rb
@@ -16,9 +16,20 @@ require 'webrick/httpservlet/abstract'
module WEBrick
module HTTPServlet
+ ##
+ # Servlet for handling CGI scripts
+ #
+ # Example:
+ #
+ # server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler,
+ # '/path/to/my_script')
+
class CGIHandler < AbstractServlet
- Ruby = RbConfig.ruby
- CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\""
+ Ruby = RbConfig.ruby # :nodoc:
+ CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc:
+
+ ##
+ # Creates a new CGI script servlet for the script at +name+
def initialize(server, name)
super(server, name)
@@ -27,6 +38,8 @@ module WEBrick
@cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
end
+ # :stopdoc:
+
def do_GET(req, res)
data = nil
status = -1
@@ -102,6 +115,8 @@ module WEBrick
res.body = body
end
alias do_POST do_GET
+
+ # :startdoc:
end
end
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
index 8736f5773a..d8c66dfdc3 100644
--- a/lib/webrick/httpservlet/filehandler.rb
+++ b/lib/webrick/httpservlet/filehandler.rb
@@ -18,12 +18,29 @@ require 'webrick/httpstatus'
module WEBrick
module HTTPServlet
+ ##
+ # Servlet for serving a single file. You probably want to use the
+ # FileHandler servlet instead as it handles directories and fancy indexes.
+ #
+ # Example:
+ #
+ # server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
+ # '/path/to/my_page.txt')
+ #
+ # This servlet handles If-Modified-Since and Range requests.
+
class DefaultFileHandler < AbstractServlet
+
+ ##
+ # Creates a DefaultFileHandler instance for the file at +local_path+.
+
def initialize(server, local_path)
super(server, local_path)
@local_path = local_path
end
+ # :stopdoc:
+
def do_GET(req, res)
st = File::stat(@local_path)
mtime = st.mtime
@@ -123,13 +140,20 @@ module WEBrick
last = filesize - 1 if last >= filesize
return first, last
end
+
+ # :startdoc:
end
##
- # Serves files from a directory
+ # Serves a directory including fancy indexing and a variety of other
+ # options.
+ #
+ # Example:
+ #
+ # server.mount '/assets', WEBrick::FileHandler, '/path/to/assets'
class FileHandler < AbstractServlet
- HandlerTable = Hash.new
+ HandlerTable = Hash.new # :nodoc:
##
# Allow custom handling of requests for files with +suffix+ by class
@@ -150,19 +174,8 @@ module WEBrick
# Creates a FileHandler servlet on +server+ that serves files starting
# at directory +root+
#
- # If +options+ is a Hash the following keys are allowed:
- #
- # :AcceptableLanguages:: Array of languages allowed for accept-language
- # :DirectoryCallback:: Allows preprocessing of directory requests
- # :FancyIndexing:: If true, show an index for directories
- # :FileCallback:: Allows preprocessing of file requests
- # :HandlerCallback:: Allows preprocessing of requests
- # :HandlerTable:: Maps file suffixes to file handlers.
- # DefaultFileHandler is used by default but any servlet
- # can be used.
- # :NondisclosureName:: Do not show files matching this array of globs
- # :UserDir:: Directory inside ~user to serve content from for /~user
- # requests. Only works if mounted on /
+ # +options+ may be a Hash containing keys from
+ # WEBrick::Config::FileHandler or +true+ or +false+.
#
# If +options+ is true or false then +:FancyIndexing+ is enabled or
# disabled respectively.
@@ -177,6 +190,8 @@ module WEBrick
@options = default.dup.update(options)
end
+ # :stopdoc:
+
def service(req, res)
# if this class is mounted on "/" and /~username is requested.
# we're going to override path informations before invoking service.
@@ -465,6 +480,7 @@ module WEBrick
_end_of_html_
end
+ # :startdoc:
end
end
end
diff --git a/lib/webrick/httpservlet/prochandler.rb b/lib/webrick/httpservlet/prochandler.rb
index 2be3c854c1..2f5aa66f45 100644
--- a/lib/webrick/httpservlet/prochandler.rb
+++ b/lib/webrick/httpservlet/prochandler.rb
@@ -13,7 +13,19 @@ require 'webrick/httpservlet/abstract.rb'
module WEBrick
module HTTPServlet
+ ##
+ # Mounts a proc at a path that accepts a request and response.
+ #
+ # Instead of mounting this servlet with WEBrick::HTTPServer#mount use
+ # WEBrick::HTTPServer#mount_proc:
+ #
+ # server.mount_proc '/' do |req, res|
+ # res.body = 'it worked!'
+ # res.status = 200
+ # end
+
class ProcHandler < AbstractServlet
+ # :stopdoc:
def get_instance(server, *options)
self
end
@@ -27,6 +39,7 @@ module WEBrick
end
alias do_POST do_GET
+ # :startdoc:
end
end
diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb
index 57ae364b35..a0ca3a48c7 100644
--- a/lib/webrick/httputils.rb
+++ b/lib/webrick/httputils.rb
@@ -12,12 +12,21 @@ require 'socket'
require 'tempfile'
module WEBrick
- CR = "\x0d"
- LF = "\x0a"
- CRLF = "\x0d\x0a"
+ CR = "\x0d" # :nodoc:
+ LF = "\x0a" # :nodoc:
+ CRLF = "\x0d\x0a" # :nodoc:
+
+ ##
+ # HTTPUtils provides utility methods for working with the HTTP protocol.
+ #
+ # This module is generally used internally by WEBrick
module HTTPUtils
+ ##
+ # Normalizes a request path. Raises an exception if the path cannot be
+ # normalized.
+
def normalize_path(path)
raise "abnormal path `#{path}'" if path[0] != ?/
ret = path.dup
@@ -31,7 +40,8 @@ module WEBrick
end
module_function :normalize_path
- #####
+ ##
+ # Default mime types
DefaultMimeTypes = {
"ai" => "application/postscript",
@@ -92,7 +102,9 @@ module WEBrick
"zip" => "application/zip",
}
- # Load Apache compatible mime.types file.
+ ##
+ # Loads Apache-compatible mime.types in +file+.
+
def load_mime_types(file)
open(file){ |io|
hash = Hash.new
@@ -109,6 +121,10 @@ module WEBrick
end
module_function :load_mime_types
+ ##
+ # Returns the mime type of +filename+ from the list in +mime_tab+. If no
+ # mime type was found application/octet-stream is returned.
+
def mime_type(filename, mime_tab)
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
@@ -116,7 +132,9 @@ module WEBrick
end
module_function :mime_type
- #####
+ ##
+ # Parses an HTTP header +raw+ into a hash of header fields with an Array
+ # of values.
def parse_header(raw)
header = Hash.new([].freeze)
@@ -148,12 +166,18 @@ module WEBrick
end
module_function :parse_header
+ ##
+ # Splits a header value +str+ according to HTTP specification.
+
def split_header_value(str)
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
(?:,\s*|\Z)'xn).flatten
end
module_function :split_header_value
+ ##
+ # Parses a Range header value +ranges_specifier+
+
def parse_range_header(ranges_specifier)
if /^bytes=(.*)/ =~ ranges_specifier
byte_range_set = split_header_value($1)
@@ -169,6 +193,9 @@ module WEBrick
end
module_function :parse_range_header
+ ##
+ # Parses q values in +value+ as used in Accept headers.
+
def parse_qvalues(value)
tmp = []
if value
@@ -187,7 +214,8 @@ module WEBrick
end
module_function :parse_qvalues
- #####
+ ##
+ # Removes quotes and escapes from +str+
def dequote(str)
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
@@ -196,20 +224,43 @@ module WEBrick
end
module_function :dequote
+ ##
+ # Quotes and escapes quotes in +str+
+
def quote(str)
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
end
module_function :quote
- #####
+ ##
+ # Stores multipart form data. FormData objects are created when
+ # WEBrick::HTTPUtils.parse_form_data is called.
class FormData < String
- EmptyRawHeader = [].freeze
- EmptyHeader = {}.freeze
+ EmptyRawHeader = [].freeze # :nodoc:
+ EmptyHeader = {}.freeze # :nodoc:
+
+ ##
+ # The name of the form data part
- attr_accessor :name, :filename, :next_data
+ attr_accessor :name
+
+ ##
+ # The filename of the form data part
+
+ attr_accessor :filename
+
+ attr_accessor :next_data # :nodoc:
protected :next_data
+ ##
+ # Creates a new FormData object.
+ #
+ # +args+ is an Array of form data entries. One FormData will be created
+ # for each entry.
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you
+
def initialize(*args)
@name = @filename = @next_data = nil
if args.empty?
@@ -226,6 +277,9 @@ module WEBrick
end
end
+ ##
+ # Retrieves the header at the first entry in +key+
+
def [](*key)
begin
@header[key[0].downcase].join(", ")
@@ -234,6 +288,12 @@ module WEBrick
end
end
+ ##
+ # Adds +str+ to this FormData which may be the body, a header or a
+ # header entry.
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you
+
def <<(str)
if @header
super
@@ -249,6 +309,11 @@ module WEBrick
self
end
+ ##
+ # Adds +data+ at the end of the chain of entries
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you.
+
def append_data(data)
tmp = self
while tmp
@@ -261,6 +326,9 @@ module WEBrick
self
end
+ ##
+ # Yields each entry in this FormData
+
def each_data
tmp = self
while tmp
@@ -270,6 +338,9 @@ module WEBrick
end
end
+ ##
+ # Returns all the FormData as an Array
+
def list
ret = []
each_data{|data|
@@ -278,13 +349,22 @@ module WEBrick
ret
end
+ ##
+ # A FormData will behave like an Array
+
alias :to_ary :list
+ ##
+ # This FormData's body
+
def to_s
String.new(self)
end
end
+ ##
+ # Parses the query component of a URI in +str+
+
def parse_query(str)
query = Hash.new
if str
@@ -306,6 +386,9 @@ module WEBrick
end
module_function :parse_query
+ ##
+ # Parses form data in +io+ with the given +boundary+
+
def parse_form_data(io, boundary)
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
form_data = Hash.new
@@ -350,6 +433,8 @@ module WEBrick
module_function
+ # :stopdoc:
+
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1.ord } end
@@ -361,24 +446,41 @@ module WEBrick
ESCAPED = /%([0-9a-fA-F]{2})/
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
+ # :startdoc:
+
+ ##
+ # Escapes HTTP reserved and unwise characters in +str+
+
def escape(str)
_escape(str, UNESCAPED)
end
+ ##
+ # Unescapes HTTP reserved and unwise characters in +str+
+
def unescape(str)
_unescape(str, ESCAPED)
end
+ ##
+ # Escapes form reserved characters in +str+
+
def escape_form(str)
ret = _escape(str, UNESCAPED_FORM)
ret.gsub!(/ /, "+")
ret
end
+ ##
+ # Unescapes form reserved characters in +str+
+
def unescape_form(str)
_unescape(str.gsub(/\+/, " "), ESCAPED)
end
+ ##
+ # Escapes path +str+
+
def escape_path(str)
result = ""
str.scan(%r{/([^/]*)}).each{|i|
@@ -387,6 +489,9 @@ module WEBrick
return result
end
+ ##
+ # Escapes 8 bit characters in +str+
+
def escape8bit(str)
_escape(str, NONASCII)
end
diff --git a/lib/webrick/httpversion.rb b/lib/webrick/httpversion.rb
index 5cf0ee400d..cdfb957296 100644
--- a/lib/webrick/httpversion.rb
+++ b/lib/webrick/httpversion.rb
@@ -8,15 +8,33 @@
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
module WEBrick
+
+ ##
+ # Represents an HTTP protocol version
+
class HTTPVersion
include Comparable
- attr_accessor :major, :minor
+ ##
+ # The major protocol version number
+
+ attr_accessor :major
+
+ ##
+ # The minor protocol version number
+
+ attr_accessor :minor
+
+ ##
+ # Converts +version+ into an HTTPVersion
def self.convert(version)
version.is_a?(self) ? version : new(version)
end
+ ##
+ # Creates a new HTTPVersion from +version+.
+
def initialize(version)
case version
when HTTPVersion
@@ -32,6 +50,10 @@ module WEBrick
end
end
+ ##
+ # Compares this version with +other+ according to the HTTP specification
+ # rules.
+
def <=>(other)
unless other.is_a?(self.class)
other = self.class.new(other)
@@ -42,6 +64,10 @@ module WEBrick
return ret
end
+ ##
+ # The HTTP version as show in the HTTP request and response. For example,
+ # "1.1"
+
def to_s
format("%d.%d", @major, @minor)
end
diff --git a/lib/webrick/log.rb b/lib/webrick/log.rb
index 546e52700b..41cde4a740 100644
--- a/lib/webrick/log.rb
+++ b/lib/webrick/log.rb
@@ -14,8 +14,27 @@ module WEBrick
# A generic logging class
class BasicLog
- # log-level constants
- FATAL, ERROR, WARN, INFO, DEBUG = 1, 2, 3, 4, 5
+
+ # Fatal log level which indicates a server crash
+
+ FATAL = 1
+
+ # Error log level which indicates a recoverable error
+
+ ERROR = 2
+
+ # Warning log level which indicates a possible problem
+
+ WARN = 3
+
+ # Information log level which indicates possibly useful information
+
+ INFO = 4
+
+ # Debugging error level for messages used in server development or
+ # debugging
+
+ DEBUG = 5
# log-level, messages above this level will be logged
attr_accessor :level
diff --git a/lib/webrick/server.rb b/lib/webrick/server.rb
index 2eabf5d55c..3f5371ba47 100644
--- a/lib/webrick/server.rb
+++ b/lib/webrick/server.rb
@@ -15,9 +15,19 @@ require 'webrick/log'
module WEBrick
+ ##
+ # Server error exception
+
class ServerError < StandardError; end
+ ##
+ # Base server class
+
class SimpleServer
+
+ ##
+ # A SimpleServer only yields when you start it
+
def SimpleServer.start
yield
end
@@ -45,8 +55,41 @@ module WEBrick
end
end
+ ##
+ # Base TCP server class. You must subclass GenericServer and provide a #run
+ # method.
+
class GenericServer
- attr_reader :status, :config, :logger, :tokens, :listeners
+
+ ##
+ # The server status. One of :Stop, :Running or :Shutdown
+
+ attr_reader :status
+
+ ##
+ # The server configuration
+
+ attr_reader :config
+
+ ##
+ # The server logger. This is independent from the HTTP access log.
+
+ attr_reader :logger
+
+ ##
+ # Tokens control the number of outstanding clients. The
+ # <code>:MaxClients</code> configuration sets this.
+
+ attr_reader :tokens
+
+ ##
+ # Sockets listening for connections.
+
+ attr_reader :listeners
+
+ ##
+ # Creates a new generic server from +config+. The default configuration
+ # comes from +default+.
def initialize(config={}, default=Config::General)
@config = default.dup.update(config)
@@ -74,10 +117,17 @@ module WEBrick
end
end
+ ##
+ # Retrieves +key+ from the configuration
+
def [](key)
@config[key]
end
+ ##
+ # Adds listeners from +address+ and +port+ to the server. See
+ # WEBrick::Utils::create_listeners for details.
+
def listen(address, port)
@listeners += Utils::create_listeners(address, port, @logger)
end
@@ -189,12 +239,22 @@ module WEBrick
@listeners.clear
end
+ ##
+ # You must subclass GenericServer and implement \#run which accepts a TCP
+ # client socket
+
def run(sock)
@logger.fatal "run() must be provided by user."
end
private
+ # :stopdoc:
+
+ ##
+ # Accepts a TCP client socket from the TCP server socket +svr+ and returns
+ # the client socket.
+
def accept_client(svr)
sock = nil
begin
@@ -211,6 +271,15 @@ module WEBrick
return sock
end
+ ##
+ # Starts a server thread for the client socket +sock+ that runs the given
+ # +block+.
+ #
+ # Sets the socket to the <code>:WEBrickSocket</code> thread local variable
+ # in the thread.
+ #
+ # If any errors occur in the block they are logged and handled.
+
def start_thread(sock, &block)
Thread.start{
begin
@@ -244,6 +313,9 @@ module WEBrick
}
end
+ ##
+ # Calls the callback +callback_name+ from the configuration with +args+
+
def call_callback(callback_name, *args)
if cb = @config[callback_name]
cb.call(*args)
diff --git a/lib/webrick/ssl.rb b/lib/webrick/ssl.rb
index 02f1be5c21..cf0f3ddb23 100644
--- a/lib/webrick/ssl.rb
+++ b/lib/webrick/ssl.rb
@@ -12,6 +12,53 @@ module WEBrick
module Config
svrsoft = General[:ServerSoftware]
osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
+
+ ##
+ # Default SSL server configuration.
+ #
+ # WEBrick can automatically create a self-signed certificate if
+ # <code>:SSLCertName</code> is set. For more information on the various
+ # SSL options see OpenSSL::SSL::SSLContext.
+ #
+ # :ServerSoftware ::
+ # The server software name used in the Server: header.
+ # :SSLEnable :: false,
+ # Enable SSL for this server. Defaults to false.
+ # :SSLCertificate ::
+ # The SSL certificate for the server.
+ # :SSLPrivateKey ::
+ # The SSL private key for the server certificate.
+ # :SSLClientCA :: nil,
+ # Array of certificates that will be sent to the client.
+ # :SSLExtraChainCert :: nil,
+ # Array of certificates that willbe added to the certificate chain
+ # :SSLCACertificateFile :: nil,
+ # Path to a CA certificate file
+ # :SSLCACertificatePath :: nil,
+ # Path to a directory containing CA certificates
+ # :SSLCertificateStore :: nil,
+ # OpenSSL::X509::Store used for certificate validation of the client
+ # :SSLTmpDhCallback :: nil,
+ # Callback invoked when DH parameters are required.
+ # :SSLVerifyClient ::
+ # Sets whether the client is verified. This defaults to VERIFY_NONE
+ # which is typical for an HTTPS server.
+ # :SSLVerifyDepth ::
+ # Number of CA certificates to walk when verifying a certificate chain
+ # :SSLVerifyCallback ::
+ # Custom certificate verification callback
+ # :SSLTimeout ::
+ # Maximum session lifetime
+ # :SSLOptions ::
+ # Various SSL options
+ # :SSLStartImmediately ::
+ # Immediately start SSL upon connection? Defaults to true
+ # :SSLCertName ::
+ # SSL certificate name. Must be set to enable automatic certificate
+ # creation.
+ # :SSLCertComment ::
+ # Comment used during automatic certificate creation.
+
SSL = {
:ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
:SSLEnable => false,
@@ -37,6 +84,10 @@ module WEBrick
end
module Utils
+ ##
+ # Creates a self-signed certificate with the given number of +bits+,
+ # the issuer +cn+ and a +comment+ to be stored in the certificate.
+
def create_self_signed_cert(bits, cn, comment)
rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
case p
@@ -79,13 +130,25 @@ module WEBrick
module_function :create_self_signed_cert
end
+ ##
+ #--
+ # Updates WEBrick::GenericServer with SSL functionality
+
class GenericServer
- def ssl_context
+
+ ##
+ # SSL context for the server when run in SSL mode
+
+ def ssl_context # :nodoc:
@ssl_context ||= nil
end
undef listen
- def listen(address, port)
+
+ ##
+ # Updates +listen+ to enable SSL when the SSL configuration is active.
+
+ def listen(address, port) # :nodoc:
listeners = Utils::create_listeners(address, port, @logger)
if @config[:SSLEnable]
unless ssl_context
@@ -101,7 +164,10 @@ module WEBrick
@listeners += listeners
end
- def setup_ssl_context(config)
+ ##
+ # Sets up an SSL context for +config+
+
+ def setup_ssl_context(config) # :nodoc:
unless config[:SSLCertificate]
cn = config[:SSLCertName]
comment = config[:SSLCertComment]
diff --git a/lib/webrick/utils.rb b/lib/webrick/utils.rb
index eab2375968..f2373572ce 100644
--- a/lib/webrick/utils.rb
+++ b/lib/webrick/utils.rb
@@ -170,6 +170,9 @@ module WEBrick
}
end
+ ##
+ # Creates a new TimeoutHandler. You should use ::register and ::cancel
+ # instead of creating the timeout handler directly.
def initialize
@timeout_info = Hash.new
Thread.start{
diff --git a/lib/webrick/version.rb b/lib/webrick/version.rb
index a49090828d..48bdc6d94d 100644
--- a/lib/webrick/version.rb
+++ b/lib/webrick/version.rb
@@ -9,5 +9,9 @@
# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
module WEBrick
+
+ ##
+ # The WEBrick version
+
VERSION = "1.3.1"
end