mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
89232d1dd9
commit
28afe277a8
23 changed files with 839 additions and 85 deletions
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
||||||
|
Sat Jan 26 10:09:57 2013 Eric Hodel <drbrain@segment7.net>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
Sat Jan 26 08:29:33 2013 Shugo Maeda <shugo@ruby-lang.org>
|
Sat Jan 26 08:29:33 2013 Shugo Maeda <shugo@ruby-lang.org>
|
||||||
|
|
||||||
* ext/socket/raddrinfo (rsock_unix_sockaddr_len): renamed from
|
* ext/socket/raddrinfo (rsock_unix_sockaddr_len): renamed from
|
||||||
|
|
|
@ -115,6 +115,10 @@ module WEBrick
|
||||||
params
|
params
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Formats +params+ according to +format_string+ which is described in
|
||||||
|
# setup_params.
|
||||||
|
|
||||||
def format(format_string, params)
|
def format(format_string, params)
|
||||||
format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
|
format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
|
||||||
param, spec = $1, $2
|
param, spec = $1, $2
|
||||||
|
@ -140,6 +144,9 @@ module WEBrick
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Escapes control characters in +data+
|
||||||
|
|
||||||
def escape(data)
|
def escape(data)
|
||||||
if data.tainted?
|
if data.tainted?
|
||||||
data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint
|
data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint
|
||||||
|
|
|
@ -13,10 +13,44 @@ require "webrick/config"
|
||||||
require "stringio"
|
require "stringio"
|
||||||
|
|
||||||
module WEBrick
|
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
|
class CGI
|
||||||
|
|
||||||
|
# The CGI error exception class
|
||||||
|
|
||||||
CGIError = Class.new(StandardError)
|
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)
|
def initialize(*args)
|
||||||
if defined?(MOD_RUBY)
|
if defined?(MOD_RUBY)
|
||||||
|
@ -41,10 +75,17 @@ module WEBrick
|
||||||
@options = args
|
@options = args
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Reads +key+ from the configuration
|
||||||
|
|
||||||
def [](key)
|
def [](key)
|
||||||
@config[key]
|
@config[key]
|
||||||
end
|
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)
|
def start(env=ENV, stdin=$stdin, stdout=$stdout)
|
||||||
sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout)
|
sock = WEBrick::CGI::Socket.new(@config, env, stdin, stdout)
|
||||||
req = HTTPRequest.new(@config)
|
req = HTTPRequest.new(@config)
|
||||||
|
@ -108,6 +149,10 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Services the request +req+ which will fill in the response +res+. See
|
||||||
|
# WEBrick::HTTPServlet::AbstractServlet#service for details.
|
||||||
|
|
||||||
def service(req, res)
|
def service(req, res)
|
||||||
method_name = "do_" + req.request_method.gsub(/-/, "_")
|
method_name = "do_" + req.request_method.gsub(/-/, "_")
|
||||||
if respond_to?(method_name)
|
if respond_to?(method_name)
|
||||||
|
@ -118,7 +163,10 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Socket
|
##
|
||||||
|
# Provides HTTP socket emulation from the CGI environment
|
||||||
|
|
||||||
|
class Socket # :nodoc:
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -16,7 +16,7 @@ require 'webrick/log'
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
module Config
|
module Config
|
||||||
LIBDIR = File::dirname(__FILE__)
|
LIBDIR = File::dirname(__FILE__) # :nodoc:
|
||||||
|
|
||||||
# for GenericServer
|
# for GenericServer
|
||||||
General = {
|
General = {
|
||||||
|
@ -67,6 +67,30 @@ module WEBrick
|
||||||
:Escape8bitURI => false
|
: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 = {
|
FileHandler = {
|
||||||
:NondisclosureName => [".ht*", "*~"],
|
:NondisclosureName => [".ht*", "*~"],
|
||||||
:FancyIndexing => false,
|
:FancyIndexing => false,
|
||||||
|
@ -78,6 +102,12 @@ module WEBrick
|
||||||
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##
|
||||||
|
# Default configuration for WEBrick::HTTPAuth::BasicAuth
|
||||||
|
#
|
||||||
|
# :AutoReloadUserDB:: Reload the user database provided by :UserDB
|
||||||
|
# automatically?
|
||||||
|
|
||||||
BasicAuth = {
|
BasicAuth = {
|
||||||
:AutoReloadUserDB => true,
|
:AutoReloadUserDB => true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,14 +12,56 @@ require 'time'
|
||||||
require 'webrick/httputils'
|
require 'webrick/httputils'
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
|
|
||||||
|
##
|
||||||
|
# Processes HTTP cookies
|
||||||
|
|
||||||
class Cookie
|
class Cookie
|
||||||
|
|
||||||
|
##
|
||||||
|
# The cookie name
|
||||||
|
|
||||||
attr_reader :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
|
#attr_accessor :comment_url, :discard, :port
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a new cookie with the given +name+ and +value+
|
||||||
|
|
||||||
def initialize(name, value)
|
def initialize(name, value)
|
||||||
@name = name
|
@name = name
|
||||||
@value = value
|
@value = value
|
||||||
|
@ -29,14 +71,25 @@ module WEBrick
|
||||||
@expires = @comment_url = @discard = @port = nil
|
@expires = @comment_url = @discard = @port = nil
|
||||||
end
|
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)
|
def expires=(t)
|
||||||
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
|
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Retrieves the expiration time as a Time
|
||||||
|
|
||||||
def expires
|
def expires
|
||||||
@expires && Time.parse(@expires)
|
@expires && Time.parse(@expires)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The cookie string suitable for use in an HTTP header
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
ret = ""
|
ret = ""
|
||||||
ret << @name << "=" << @value
|
ret << @name << "=" << @value
|
||||||
|
@ -50,8 +103,10 @@ module WEBrick
|
||||||
ret
|
ret
|
||||||
end
|
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)
|
def self.parse(str)
|
||||||
if str
|
if str
|
||||||
ret = []
|
ret = []
|
||||||
|
@ -76,6 +131,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses the cookie in +str+
|
||||||
|
|
||||||
def self.parse_set_cookie(str)
|
def self.parse_set_cookie(str)
|
||||||
cookie_elem = str.split(/;/)
|
cookie_elem = str.split(/;/)
|
||||||
first_elem = cookie_elem.shift
|
first_elem = cookie_elem.shift
|
||||||
|
@ -101,6 +159,9 @@ module WEBrick
|
||||||
return cookie
|
return cookie
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses the cookies in +str+
|
||||||
|
|
||||||
def self.parse_set_cookies(str)
|
def self.parse_set_cookies(str)
|
||||||
return str.split(/,(?=[^;,]*=)|,$/).collect{|c|
|
return str.split(/,(?=[^;,]*=)|,$/).collect{|c|
|
||||||
parse_set_cookie(c)
|
parse_set_cookie(c)
|
||||||
|
|
|
@ -16,10 +16,10 @@ module WEBrick
|
||||||
|
|
||||||
module Authenticator
|
module Authenticator
|
||||||
|
|
||||||
RequestField = "Authorization"
|
RequestField = "Authorization" # :nodoc:
|
||||||
ResponseField = "WWW-Authenticate"
|
ResponseField = "WWW-Authenticate" # :nodoc:
|
||||||
ResponseInfoField = "Authentication-Info"
|
ResponseInfoField = "Authentication-Info" # :nodoc:
|
||||||
AuthException = HTTPStatus::Unauthorized
|
AuthException = HTTPStatus::Unauthorized # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Method of authentication, must be overridden by the including class
|
# Method of authentication, must be overridden by the including class
|
||||||
|
@ -43,6 +43,8 @@ module WEBrick
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Initializes the authenticator from +config+
|
# Initializes the authenticator from +config+
|
||||||
|
|
||||||
|
@ -96,6 +98,8 @@ module WEBrick
|
||||||
log(:info, fmt, *args)
|
log(:info, fmt, *args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -103,10 +107,10 @@ module WEBrick
|
||||||
# authentication schemes for proxies.
|
# authentication schemes for proxies.
|
||||||
|
|
||||||
module ProxyAuthenticator
|
module ProxyAuthenticator
|
||||||
RequestField = "Proxy-Authorization"
|
RequestField = "Proxy-Authorization" # :nodoc:
|
||||||
ResponseField = "Proxy-Authenticate"
|
ResponseField = "Proxy-Authenticate" # :nodoc:
|
||||||
InfoField = "Proxy-Authentication-Info"
|
InfoField = "Proxy-Authentication-Info" # :nodoc:
|
||||||
AuthException = HTTPStatus::ProxyAuthenticationRequired
|
AuthException = HTTPStatus::ProxyAuthenticationRequired # :nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ module WEBrick
|
||||||
class BasicAuth
|
class BasicAuth
|
||||||
include Authenticator
|
include Authenticator
|
||||||
|
|
||||||
AuthScheme = "Basic"
|
AuthScheme = "Basic" # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Used by UserDB to create a basic password entry
|
# Used by UserDB to create a basic password entry
|
||||||
|
|
|
@ -45,9 +45,22 @@ module WEBrick
|
||||||
class DigestAuth
|
class DigestAuth
|
||||||
include Authenticator
|
include Authenticator
|
||||||
|
|
||||||
AuthScheme = "Digest"
|
AuthScheme = "Digest" # :nodoc:
|
||||||
OpaqueInfo = Struct.new(:time, :nonce, :nc)
|
|
||||||
attr_reader :algorithm, :qop
|
##
|
||||||
|
# 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
|
# Used by UserDB to create a digest password entry
|
||||||
|
@ -142,6 +155,8 @@ module WEBrick
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
MustParams = ['username','realm','nonce','uri','response']
|
MustParams = ['username','realm','nonce','uri','response']
|
||||||
MustParamsAuth = ['cnonce','nc']
|
MustParamsAuth = ['cnonce','nc']
|
||||||
|
|
||||||
|
@ -375,6 +390,7 @@ module WEBrick
|
||||||
@h.hexdigest(args.join(":"))
|
@h.hexdigest(args.join(":"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -384,7 +400,7 @@ module WEBrick
|
||||||
include ProxyAuthenticator
|
include ProxyAuthenticator
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_uri(req, auth_req)
|
def check_uri(req, auth_req) # :nodoc:
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,16 +15,17 @@ require "net/http"
|
||||||
Net::HTTP::version_1_2 if RUBY_VERSION < "1.7"
|
Net::HTTP::version_1_2 if RUBY_VERSION < "1.7"
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
NullReader = Object.new
|
|
||||||
class << NullReader
|
NullReader = Object.new # :nodoc:
|
||||||
|
class << NullReader # :nodoc:
|
||||||
def read(*args)
|
def read(*args)
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
alias gets read
|
alias gets read
|
||||||
end
|
end
|
||||||
|
|
||||||
FakeProxyURI = Object.new
|
FakeProxyURI = Object.new # :nodoc:
|
||||||
class << FakeProxyURI
|
class << FakeProxyURI # :nodoc:
|
||||||
def method_missing(meth, *args)
|
def method_missing(meth, *args)
|
||||||
if %w(scheme host port path query userinfo).member?(meth.to_s)
|
if %w(scheme host port path query userinfo).member?(meth.to_s)
|
||||||
return nil
|
return nil
|
||||||
|
@ -33,6 +34,8 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# An HTTP Proxy server which proxies GET, HEAD and POST requests.
|
# An HTTP Proxy server which proxies GET, HEAD and POST requests.
|
||||||
#
|
#
|
||||||
|
@ -85,6 +88,7 @@ module WEBrick
|
||||||
@via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
|
@via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
def service(req, res)
|
def service(req, res)
|
||||||
if req.request_method == "CONNECT"
|
if req.request_method == "CONNECT"
|
||||||
do_CONNECT(req, res)
|
do_CONNECT(req, res)
|
||||||
|
@ -329,5 +333,7 @@ module WEBrick
|
||||||
set_via(res)
|
set_via(res)
|
||||||
res.body = response.body
|
res.body = response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,31 +17,137 @@ require 'webrick/cookie'
|
||||||
module WEBrick
|
module WEBrick
|
||||||
|
|
||||||
##
|
##
|
||||||
# An HTTP request.
|
# An HTTP request. This is consumed by service and do_* methods in
|
||||||
|
# WEBrick servlets
|
||||||
|
|
||||||
class HTTPRequest
|
class HTTPRequest
|
||||||
|
|
||||||
BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ]
|
BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
|
||||||
|
|
||||||
# :section: Request line
|
# :section: Request line
|
||||||
|
|
||||||
|
##
|
||||||
|
# The complete request line such as:
|
||||||
|
#
|
||||||
|
# GET / HTTP/1.1
|
||||||
|
|
||||||
attr_reader :request_line
|
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
|
# :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
|
# :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:
|
# :section:
|
||||||
|
|
||||||
|
##
|
||||||
|
# The remote user (CGI variable)
|
||||||
|
|
||||||
attr_accessor :user
|
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
|
attr_reader :attributes
|
||||||
|
|
||||||
|
##
|
||||||
|
# Is this a keep-alive connection?
|
||||||
|
|
||||||
attr_reader :keep_alive
|
attr_reader :keep_alive
|
||||||
|
|
||||||
|
##
|
||||||
|
# The local time this request was received
|
||||||
|
|
||||||
attr_reader :request_time
|
attr_reader :request_time
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a new HTTP request. WEBrick::Config::HTTP is the default
|
||||||
|
# configuration.
|
||||||
|
|
||||||
def initialize(config)
|
def initialize(config)
|
||||||
@config = config
|
@config = config
|
||||||
@buffer_size = @config[:InputBufferSize]
|
@buffer_size = @config[:InputBufferSize]
|
||||||
|
@ -78,6 +184,10 @@ module WEBrick
|
||||||
@forwarded_server = @forwarded_for = nil
|
@forwarded_server = @forwarded_for = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses a request from +socket+. This is called internally by
|
||||||
|
# WEBrick::HTTPServer.
|
||||||
|
|
||||||
def parse(socket=nil)
|
def parse(socket=nil)
|
||||||
@socket = socket
|
@socket = socket
|
||||||
begin
|
begin
|
||||||
|
@ -126,16 +236,21 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
# Generate HTTP/1.1 100 continue response if the client expects it,
|
# Generate HTTP/1.1 100 continue response if the client expects it,
|
||||||
# otherwise does nothing.
|
# otherwise does nothing.
|
||||||
def continue
|
|
||||||
|
def continue # :nodoc:
|
||||||
if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
|
if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
|
||||||
@socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
|
@socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
|
||||||
@header.delete('expect')
|
@header.delete('expect')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def body(&block)
|
##
|
||||||
|
# Returns the request body.
|
||||||
|
|
||||||
|
def body(&block) # :yields: body_chunk
|
||||||
block ||= Proc.new{|chunk| @body << chunk }
|
block ||= Proc.new{|chunk| @body << chunk }
|
||||||
read_body(@socket, block)
|
read_body(@socket, block)
|
||||||
@body.empty? ? nil : @body
|
@body.empty? ? nil : @body
|
||||||
|
@ -237,7 +352,10 @@ module WEBrick
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def fixup()
|
##
|
||||||
|
# Consumes any remaining body and updates keep-alive status
|
||||||
|
|
||||||
|
def fixup() # :nodoc:
|
||||||
begin
|
begin
|
||||||
body{|chunk| } # read remaining body
|
body{|chunk| } # read remaining body
|
||||||
rescue HTTPStatus::Error => ex
|
rescue HTTPStatus::Error => ex
|
||||||
|
@ -290,6 +408,8 @@ module WEBrick
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
MAX_URI_LENGTH = 2083 # :nodoc:
|
MAX_URI_LENGTH = 2083 # :nodoc:
|
||||||
|
|
||||||
def read_request_line(socket)
|
def read_request_line(socket)
|
||||||
|
@ -457,5 +577,7 @@ module WEBrick
|
||||||
@forwarded_for = addrs.first
|
@forwarded_for = addrs.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,11 +16,34 @@ require 'webrick/httpstatus'
|
||||||
|
|
||||||
module WEBrick
|
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
|
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
|
attr_reader :cookies
|
||||||
|
|
||||||
|
##
|
||||||
|
# Response reason phrase ("OK")
|
||||||
|
|
||||||
attr_accessor :reason_phrase
|
attr_accessor :reason_phrase
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -28,13 +51,45 @@ module WEBrick
|
||||||
|
|
||||||
attr_accessor :body
|
attr_accessor :body
|
||||||
|
|
||||||
attr_accessor :request_method, :request_uri, :request_http_version
|
##
|
||||||
attr_accessor :filename
|
# Request method for this response
|
||||||
attr_accessor :keep_alive
|
|
||||||
attr_reader :config, :sent_size
|
attr_accessor :request_method
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new HTTP response object
|
# 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
|
||||||
|
|
||||||
|
##
|
||||||
|
# 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)
|
def initialize(config)
|
||||||
@config = config
|
@config = config
|
||||||
|
@ -145,7 +200,7 @@ module WEBrick
|
||||||
##
|
##
|
||||||
# Sends the response on +socket+
|
# Sends the response on +socket+
|
||||||
|
|
||||||
def send_response(socket)
|
def send_response(socket) # :nodoc:
|
||||||
begin
|
begin
|
||||||
setup_header()
|
setup_header()
|
||||||
send_header(socket)
|
send_header(socket)
|
||||||
|
@ -162,7 +217,7 @@ module WEBrick
|
||||||
##
|
##
|
||||||
# Sets up the headers for sending
|
# Sets up the headers for sending
|
||||||
|
|
||||||
def setup_header()
|
def setup_header() # :nodoc:
|
||||||
@reason_phrase ||= HTTPStatus::reason_phrase(@status)
|
@reason_phrase ||= HTTPStatus::reason_phrase(@status)
|
||||||
@header['server'] ||= @config[:ServerSoftware]
|
@header['server'] ||= @config[:ServerSoftware]
|
||||||
@header['date'] ||= Time.now.httpdate
|
@header['date'] ||= Time.now.httpdate
|
||||||
|
@ -225,7 +280,7 @@ module WEBrick
|
||||||
##
|
##
|
||||||
# Sends the headers on +socket+
|
# Sends the headers on +socket+
|
||||||
|
|
||||||
def send_header(socket)
|
def send_header(socket) # :nodoc:
|
||||||
if @http_version.major > 0
|
if @http_version.major > 0
|
||||||
data = status_line()
|
data = status_line()
|
||||||
@header.each{|key, value|
|
@header.each{|key, value|
|
||||||
|
@ -243,7 +298,7 @@ module WEBrick
|
||||||
##
|
##
|
||||||
# Sends the body on +socket+
|
# Sends the body on +socket+
|
||||||
|
|
||||||
def send_body(socket)
|
def send_body(socket) # :nodoc:
|
||||||
case @body
|
case @body
|
||||||
when IO then send_body_io(socket)
|
when IO then send_body_io(socket)
|
||||||
else send_body_string(socket)
|
else send_body_string(socket)
|
||||||
|
@ -325,6 +380,8 @@ module WEBrick
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
def send_body_io(socket)
|
def send_body_io(socket)
|
||||||
begin
|
begin
|
||||||
if @request_method == "HEAD"
|
if @request_method == "HEAD"
|
||||||
|
@ -400,5 +457,8 @@ module WEBrick
|
||||||
def _write_data(socket, data)
|
def _write_data(socket, data)
|
||||||
socket << data
|
socket << data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,8 +15,28 @@ module WEBrick
|
||||||
HTTP.update(SSL)
|
HTTP.update(SSL)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
#--
|
||||||
|
# Adds SSL functionality to WEBrick::HTTPRequest
|
||||||
|
|
||||||
class 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
|
alias orig_parse parse
|
||||||
|
|
||||||
|
@ -60,5 +80,7 @@ module WEBrick
|
||||||
end
|
end
|
||||||
meta
|
meta
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -138,6 +138,10 @@ module WEBrick
|
||||||
si.service(req, res)
|
si.service(req, res)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The default OPTIONS request handler says GET, HEAD, POST and OPTIONS
|
||||||
|
# requests are allowed.
|
||||||
|
|
||||||
def do_OPTIONS(req, res)
|
def do_OPTIONS(req, res)
|
||||||
res["allow"] = "GET,HEAD,POST,OPTIONS"
|
res["allow"] = "GET,HEAD,POST,OPTIONS"
|
||||||
end
|
end
|
||||||
|
@ -207,6 +211,10 @@ module WEBrick
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Logs +req+ and +res+ in the access logs. +config+ is used for the
|
||||||
|
# server name.
|
||||||
|
|
||||||
def access_log(config, req, res)
|
def access_log(config, req, res)
|
||||||
param = AccessLog::setup_params(config, req, res)
|
param = AccessLog::setup_params(config, req, res)
|
||||||
@config[:AccessLog].each{|logger, fmt|
|
@config[:AccessLog].each{|logger, fmt|
|
||||||
|
@ -214,7 +222,13 @@ module WEBrick
|
||||||
}
|
}
|
||||||
end
|
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
|
def initialize
|
||||||
@tab = Hash.new
|
@tab = Hash.new
|
||||||
compile
|
compile
|
||||||
|
|
|
@ -16,9 +16,20 @@ require 'webrick/httpservlet/abstract'
|
||||||
module WEBrick
|
module WEBrick
|
||||||
module HTTPServlet
|
module HTTPServlet
|
||||||
|
|
||||||
|
##
|
||||||
|
# Servlet for handling CGI scripts
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler,
|
||||||
|
# '/path/to/my_script')
|
||||||
|
|
||||||
class CGIHandler < AbstractServlet
|
class CGIHandler < AbstractServlet
|
||||||
Ruby = RbConfig.ruby
|
Ruby = RbConfig.ruby # :nodoc:
|
||||||
CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\""
|
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)
|
def initialize(server, name)
|
||||||
super(server, name)
|
super(server, name)
|
||||||
|
@ -27,6 +38,8 @@ module WEBrick
|
||||||
@cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
|
@cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
def do_GET(req, res)
|
def do_GET(req, res)
|
||||||
data = nil
|
data = nil
|
||||||
status = -1
|
status = -1
|
||||||
|
@ -102,6 +115,8 @@ module WEBrick
|
||||||
res.body = body
|
res.body = body
|
||||||
end
|
end
|
||||||
alias do_POST do_GET
|
alias do_POST do_GET
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,12 +18,29 @@ require 'webrick/httpstatus'
|
||||||
module WEBrick
|
module WEBrick
|
||||||
module HTTPServlet
|
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
|
class DefaultFileHandler < AbstractServlet
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a DefaultFileHandler instance for the file at +local_path+.
|
||||||
|
|
||||||
def initialize(server, local_path)
|
def initialize(server, local_path)
|
||||||
super(server, local_path)
|
super(server, local_path)
|
||||||
@local_path = local_path
|
@local_path = local_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
def do_GET(req, res)
|
def do_GET(req, res)
|
||||||
st = File::stat(@local_path)
|
st = File::stat(@local_path)
|
||||||
mtime = st.mtime
|
mtime = st.mtime
|
||||||
|
@ -123,13 +140,20 @@ module WEBrick
|
||||||
last = filesize - 1 if last >= filesize
|
last = filesize - 1 if last >= filesize
|
||||||
return first, last
|
return first, last
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
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
|
class FileHandler < AbstractServlet
|
||||||
HandlerTable = Hash.new
|
HandlerTable = Hash.new # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Allow custom handling of requests for files with +suffix+ by class
|
# 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
|
# Creates a FileHandler servlet on +server+ that serves files starting
|
||||||
# at directory +root+
|
# at directory +root+
|
||||||
#
|
#
|
||||||
# If +options+ is a Hash the following keys are allowed:
|
# +options+ may be a Hash containing keys from
|
||||||
#
|
# WEBrick::Config::FileHandler or +true+ or +false+.
|
||||||
# :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 /
|
|
||||||
#
|
#
|
||||||
# If +options+ is true or false then +:FancyIndexing+ is enabled or
|
# If +options+ is true or false then +:FancyIndexing+ is enabled or
|
||||||
# disabled respectively.
|
# disabled respectively.
|
||||||
|
@ -177,6 +190,8 @@ module WEBrick
|
||||||
@options = default.dup.update(options)
|
@options = default.dup.update(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
def service(req, res)
|
def service(req, res)
|
||||||
# if this class is mounted on "/" and /~username is requested.
|
# if this class is mounted on "/" and /~username is requested.
|
||||||
# we're going to override path informations before invoking service.
|
# we're going to override path informations before invoking service.
|
||||||
|
@ -465,6 +480,7 @@ module WEBrick
|
||||||
_end_of_html_
|
_end_of_html_
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,19 @@ require 'webrick/httpservlet/abstract.rb'
|
||||||
module WEBrick
|
module WEBrick
|
||||||
module HTTPServlet
|
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
|
class ProcHandler < AbstractServlet
|
||||||
|
# :stopdoc:
|
||||||
def get_instance(server, *options)
|
def get_instance(server, *options)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
@ -27,6 +39,7 @@ module WEBrick
|
||||||
end
|
end
|
||||||
|
|
||||||
alias do_POST do_GET
|
alias do_POST do_GET
|
||||||
|
# :startdoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,12 +12,21 @@ require 'socket'
|
||||||
require 'tempfile'
|
require 'tempfile'
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
CR = "\x0d"
|
CR = "\x0d" # :nodoc:
|
||||||
LF = "\x0a"
|
LF = "\x0a" # :nodoc:
|
||||||
CRLF = "\x0d\x0a"
|
CRLF = "\x0d\x0a" # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# HTTPUtils provides utility methods for working with the HTTP protocol.
|
||||||
|
#
|
||||||
|
# This module is generally used internally by WEBrick
|
||||||
|
|
||||||
module HTTPUtils
|
module HTTPUtils
|
||||||
|
|
||||||
|
##
|
||||||
|
# Normalizes a request path. Raises an exception if the path cannot be
|
||||||
|
# normalized.
|
||||||
|
|
||||||
def normalize_path(path)
|
def normalize_path(path)
|
||||||
raise "abnormal path `#{path}'" if path[0] != ?/
|
raise "abnormal path `#{path}'" if path[0] != ?/
|
||||||
ret = path.dup
|
ret = path.dup
|
||||||
|
@ -31,7 +40,8 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :normalize_path
|
module_function :normalize_path
|
||||||
|
|
||||||
#####
|
##
|
||||||
|
# Default mime types
|
||||||
|
|
||||||
DefaultMimeTypes = {
|
DefaultMimeTypes = {
|
||||||
"ai" => "application/postscript",
|
"ai" => "application/postscript",
|
||||||
|
@ -92,7 +102,9 @@ module WEBrick
|
||||||
"zip" => "application/zip",
|
"zip" => "application/zip",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load Apache compatible mime.types file.
|
##
|
||||||
|
# Loads Apache-compatible mime.types in +file+.
|
||||||
|
|
||||||
def load_mime_types(file)
|
def load_mime_types(file)
|
||||||
open(file){ |io|
|
open(file){ |io|
|
||||||
hash = Hash.new
|
hash = Hash.new
|
||||||
|
@ -109,6 +121,10 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :load_mime_types
|
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)
|
def mime_type(filename, mime_tab)
|
||||||
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
||||||
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
||||||
|
@ -116,7 +132,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :mime_type
|
module_function :mime_type
|
||||||
|
|
||||||
#####
|
##
|
||||||
|
# Parses an HTTP header +raw+ into a hash of header fields with an Array
|
||||||
|
# of values.
|
||||||
|
|
||||||
def parse_header(raw)
|
def parse_header(raw)
|
||||||
header = Hash.new([].freeze)
|
header = Hash.new([].freeze)
|
||||||
|
@ -148,12 +166,18 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :parse_header
|
module_function :parse_header
|
||||||
|
|
||||||
|
##
|
||||||
|
# Splits a header value +str+ according to HTTP specification.
|
||||||
|
|
||||||
def split_header_value(str)
|
def split_header_value(str)
|
||||||
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
|
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
|
||||||
(?:,\s*|\Z)'xn).flatten
|
(?:,\s*|\Z)'xn).flatten
|
||||||
end
|
end
|
||||||
module_function :split_header_value
|
module_function :split_header_value
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses a Range header value +ranges_specifier+
|
||||||
|
|
||||||
def parse_range_header(ranges_specifier)
|
def parse_range_header(ranges_specifier)
|
||||||
if /^bytes=(.*)/ =~ ranges_specifier
|
if /^bytes=(.*)/ =~ ranges_specifier
|
||||||
byte_range_set = split_header_value($1)
|
byte_range_set = split_header_value($1)
|
||||||
|
@ -169,6 +193,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :parse_range_header
|
module_function :parse_range_header
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses q values in +value+ as used in Accept headers.
|
||||||
|
|
||||||
def parse_qvalues(value)
|
def parse_qvalues(value)
|
||||||
tmp = []
|
tmp = []
|
||||||
if value
|
if value
|
||||||
|
@ -187,7 +214,8 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :parse_qvalues
|
module_function :parse_qvalues
|
||||||
|
|
||||||
#####
|
##
|
||||||
|
# Removes quotes and escapes from +str+
|
||||||
|
|
||||||
def dequote(str)
|
def dequote(str)
|
||||||
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
||||||
|
@ -196,20 +224,43 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :dequote
|
module_function :dequote
|
||||||
|
|
||||||
|
##
|
||||||
|
# Quotes and escapes quotes in +str+
|
||||||
|
|
||||||
def quote(str)
|
def quote(str)
|
||||||
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
|
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
|
||||||
end
|
end
|
||||||
module_function :quote
|
module_function :quote
|
||||||
|
|
||||||
#####
|
##
|
||||||
|
# Stores multipart form data. FormData objects are created when
|
||||||
|
# WEBrick::HTTPUtils.parse_form_data is called.
|
||||||
|
|
||||||
class FormData < String
|
class FormData < String
|
||||||
EmptyRawHeader = [].freeze
|
EmptyRawHeader = [].freeze # :nodoc:
|
||||||
EmptyHeader = {}.freeze
|
EmptyHeader = {}.freeze # :nodoc:
|
||||||
|
|
||||||
attr_accessor :name, :filename, :next_data
|
##
|
||||||
|
# The name of the form data part
|
||||||
|
|
||||||
|
attr_accessor :name
|
||||||
|
|
||||||
|
##
|
||||||
|
# The filename of the form data part
|
||||||
|
|
||||||
|
attr_accessor :filename
|
||||||
|
|
||||||
|
attr_accessor :next_data # :nodoc:
|
||||||
protected :next_data
|
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)
|
def initialize(*args)
|
||||||
@name = @filename = @next_data = nil
|
@name = @filename = @next_data = nil
|
||||||
if args.empty?
|
if args.empty?
|
||||||
|
@ -226,6 +277,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Retrieves the header at the first entry in +key+
|
||||||
|
|
||||||
def [](*key)
|
def [](*key)
|
||||||
begin
|
begin
|
||||||
@header[key[0].downcase].join(", ")
|
@header[key[0].downcase].join(", ")
|
||||||
|
@ -234,6 +288,12 @@ module WEBrick
|
||||||
end
|
end
|
||||||
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)
|
def <<(str)
|
||||||
if @header
|
if @header
|
||||||
super
|
super
|
||||||
|
@ -249,6 +309,11 @@ module WEBrick
|
||||||
self
|
self
|
||||||
end
|
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)
|
def append_data(data)
|
||||||
tmp = self
|
tmp = self
|
||||||
while tmp
|
while tmp
|
||||||
|
@ -261,6 +326,9 @@ module WEBrick
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Yields each entry in this FormData
|
||||||
|
|
||||||
def each_data
|
def each_data
|
||||||
tmp = self
|
tmp = self
|
||||||
while tmp
|
while tmp
|
||||||
|
@ -270,6 +338,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns all the FormData as an Array
|
||||||
|
|
||||||
def list
|
def list
|
||||||
ret = []
|
ret = []
|
||||||
each_data{|data|
|
each_data{|data|
|
||||||
|
@ -278,13 +349,22 @@ module WEBrick
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# A FormData will behave like an Array
|
||||||
|
|
||||||
alias :to_ary :list
|
alias :to_ary :list
|
||||||
|
|
||||||
|
##
|
||||||
|
# This FormData's body
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
String.new(self)
|
String.new(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses the query component of a URI in +str+
|
||||||
|
|
||||||
def parse_query(str)
|
def parse_query(str)
|
||||||
query = Hash.new
|
query = Hash.new
|
||||||
if str
|
if str
|
||||||
|
@ -306,6 +386,9 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :parse_query
|
module_function :parse_query
|
||||||
|
|
||||||
|
##
|
||||||
|
# Parses form data in +io+ with the given +boundary+
|
||||||
|
|
||||||
def parse_form_data(io, boundary)
|
def parse_form_data(io, boundary)
|
||||||
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
|
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
|
||||||
form_data = Hash.new
|
form_data = Hash.new
|
||||||
|
@ -350,6 +433,8 @@ module WEBrick
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
|
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
|
||||||
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
|
def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1.ord } end
|
||||||
|
@ -361,24 +446,41 @@ module WEBrick
|
||||||
ESCAPED = /%([0-9a-fA-F]{2})/
|
ESCAPED = /%([0-9a-fA-F]{2})/
|
||||||
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
|
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Escapes HTTP reserved and unwise characters in +str+
|
||||||
|
|
||||||
def escape(str)
|
def escape(str)
|
||||||
_escape(str, UNESCAPED)
|
_escape(str, UNESCAPED)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Unescapes HTTP reserved and unwise characters in +str+
|
||||||
|
|
||||||
def unescape(str)
|
def unescape(str)
|
||||||
_unescape(str, ESCAPED)
|
_unescape(str, ESCAPED)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Escapes form reserved characters in +str+
|
||||||
|
|
||||||
def escape_form(str)
|
def escape_form(str)
|
||||||
ret = _escape(str, UNESCAPED_FORM)
|
ret = _escape(str, UNESCAPED_FORM)
|
||||||
ret.gsub!(/ /, "+")
|
ret.gsub!(/ /, "+")
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Unescapes form reserved characters in +str+
|
||||||
|
|
||||||
def unescape_form(str)
|
def unescape_form(str)
|
||||||
_unescape(str.gsub(/\+/, " "), ESCAPED)
|
_unescape(str.gsub(/\+/, " "), ESCAPED)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Escapes path +str+
|
||||||
|
|
||||||
def escape_path(str)
|
def escape_path(str)
|
||||||
result = ""
|
result = ""
|
||||||
str.scan(%r{/([^/]*)}).each{|i|
|
str.scan(%r{/([^/]*)}).each{|i|
|
||||||
|
@ -387,6 +489,9 @@ module WEBrick
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Escapes 8 bit characters in +str+
|
||||||
|
|
||||||
def escape8bit(str)
|
def escape8bit(str)
|
||||||
_escape(str, NONASCII)
|
_escape(str, NONASCII)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,15 +8,33 @@
|
||||||
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
|
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
|
|
||||||
|
##
|
||||||
|
# Represents an HTTP protocol version
|
||||||
|
|
||||||
class HTTPVersion
|
class HTTPVersion
|
||||||
include Comparable
|
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)
|
def self.convert(version)
|
||||||
version.is_a?(self) ? version : new(version)
|
version.is_a?(self) ? version : new(version)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a new HTTPVersion from +version+.
|
||||||
|
|
||||||
def initialize(version)
|
def initialize(version)
|
||||||
case version
|
case version
|
||||||
when HTTPVersion
|
when HTTPVersion
|
||||||
|
@ -32,6 +50,10 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Compares this version with +other+ according to the HTTP specification
|
||||||
|
# rules.
|
||||||
|
|
||||||
def <=>(other)
|
def <=>(other)
|
||||||
unless other.is_a?(self.class)
|
unless other.is_a?(self.class)
|
||||||
other = self.class.new(other)
|
other = self.class.new(other)
|
||||||
|
@ -42,6 +64,10 @@ module WEBrick
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The HTTP version as show in the HTTP request and response. For example,
|
||||||
|
# "1.1"
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
format("%d.%d", @major, @minor)
|
format("%d.%d", @major, @minor)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,8 +14,27 @@ module WEBrick
|
||||||
# A generic logging class
|
# A generic logging class
|
||||||
|
|
||||||
class BasicLog
|
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
|
# log-level, messages above this level will be logged
|
||||||
attr_accessor :level
|
attr_accessor :level
|
||||||
|
|
|
@ -15,9 +15,19 @@ require 'webrick/log'
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
|
|
||||||
|
##
|
||||||
|
# Server error exception
|
||||||
|
|
||||||
class ServerError < StandardError; end
|
class ServerError < StandardError; end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Base server class
|
||||||
|
|
||||||
class SimpleServer
|
class SimpleServer
|
||||||
|
|
||||||
|
##
|
||||||
|
# A SimpleServer only yields when you start it
|
||||||
|
|
||||||
def SimpleServer.start
|
def SimpleServer.start
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
@ -45,8 +55,41 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Base TCP server class. You must subclass GenericServer and provide a #run
|
||||||
|
# method.
|
||||||
|
|
||||||
class GenericServer
|
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)
|
def initialize(config={}, default=Config::General)
|
||||||
@config = default.dup.update(config)
|
@config = default.dup.update(config)
|
||||||
|
@ -74,10 +117,17 @@ module WEBrick
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Retrieves +key+ from the configuration
|
||||||
|
|
||||||
def [](key)
|
def [](key)
|
||||||
@config[key]
|
@config[key]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Adds listeners from +address+ and +port+ to the server. See
|
||||||
|
# WEBrick::Utils::create_listeners for details.
|
||||||
|
|
||||||
def listen(address, port)
|
def listen(address, port)
|
||||||
@listeners += Utils::create_listeners(address, port, @logger)
|
@listeners += Utils::create_listeners(address, port, @logger)
|
||||||
end
|
end
|
||||||
|
@ -189,12 +239,22 @@ module WEBrick
|
||||||
@listeners.clear
|
@listeners.clear
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# You must subclass GenericServer and implement \#run which accepts a TCP
|
||||||
|
# client socket
|
||||||
|
|
||||||
def run(sock)
|
def run(sock)
|
||||||
@logger.fatal "run() must be provided by user."
|
@logger.fatal "run() must be provided by user."
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Accepts a TCP client socket from the TCP server socket +svr+ and returns
|
||||||
|
# the client socket.
|
||||||
|
|
||||||
def accept_client(svr)
|
def accept_client(svr)
|
||||||
sock = nil
|
sock = nil
|
||||||
begin
|
begin
|
||||||
|
@ -211,6 +271,15 @@ module WEBrick
|
||||||
return sock
|
return sock
|
||||||
end
|
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)
|
def start_thread(sock, &block)
|
||||||
Thread.start{
|
Thread.start{
|
||||||
begin
|
begin
|
||||||
|
@ -244,6 +313,9 @@ module WEBrick
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Calls the callback +callback_name+ from the configuration with +args+
|
||||||
|
|
||||||
def call_callback(callback_name, *args)
|
def call_callback(callback_name, *args)
|
||||||
if cb = @config[callback_name]
|
if cb = @config[callback_name]
|
||||||
cb.call(*args)
|
cb.call(*args)
|
||||||
|
|
|
@ -12,6 +12,53 @@ module WEBrick
|
||||||
module Config
|
module Config
|
||||||
svrsoft = General[:ServerSoftware]
|
svrsoft = General[:ServerSoftware]
|
||||||
osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
|
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 = {
|
SSL = {
|
||||||
:ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
|
:ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
|
||||||
:SSLEnable => false,
|
:SSLEnable => false,
|
||||||
|
@ -37,6 +84,10 @@ module WEBrick
|
||||||
end
|
end
|
||||||
|
|
||||||
module Utils
|
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)
|
def create_self_signed_cert(bits, cn, comment)
|
||||||
rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
|
rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
|
||||||
case p
|
case p
|
||||||
|
@ -79,13 +130,25 @@ module WEBrick
|
||||||
module_function :create_self_signed_cert
|
module_function :create_self_signed_cert
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
#--
|
||||||
|
# Updates WEBrick::GenericServer with SSL functionality
|
||||||
|
|
||||||
class GenericServer
|
class GenericServer
|
||||||
def ssl_context
|
|
||||||
|
##
|
||||||
|
# SSL context for the server when run in SSL mode
|
||||||
|
|
||||||
|
def ssl_context # :nodoc:
|
||||||
@ssl_context ||= nil
|
@ssl_context ||= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
undef listen
|
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)
|
listeners = Utils::create_listeners(address, port, @logger)
|
||||||
if @config[:SSLEnable]
|
if @config[:SSLEnable]
|
||||||
unless ssl_context
|
unless ssl_context
|
||||||
|
@ -101,7 +164,10 @@ module WEBrick
|
||||||
@listeners += listeners
|
@listeners += listeners
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_ssl_context(config)
|
##
|
||||||
|
# Sets up an SSL context for +config+
|
||||||
|
|
||||||
|
def setup_ssl_context(config) # :nodoc:
|
||||||
unless config[:SSLCertificate]
|
unless config[:SSLCertificate]
|
||||||
cn = config[:SSLCertName]
|
cn = config[:SSLCertName]
|
||||||
comment = config[:SSLCertComment]
|
comment = config[:SSLCertComment]
|
||||||
|
|
|
@ -170,6 +170,9 @@ module WEBrick
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Creates a new TimeoutHandler. You should use ::register and ::cancel
|
||||||
|
# instead of creating the timeout handler directly.
|
||||||
def initialize
|
def initialize
|
||||||
@timeout_info = Hash.new
|
@timeout_info = Hash.new
|
||||||
Thread.start{
|
Thread.start{
|
||||||
|
|
|
@ -9,5 +9,9 @@
|
||||||
# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
|
# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
|
||||||
|
|
||||||
module WEBrick
|
module WEBrick
|
||||||
|
|
||||||
|
##
|
||||||
|
# The WEBrick version
|
||||||
|
|
||||||
VERSION = "1.3.1"
|
VERSION = "1.3.1"
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue