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>
|
||||
|
||||
* ext/socket/raddrinfo (rsock_unix_sockaddr_len): renamed from
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -34,7 +34,7 @@ module WEBrick
|
|||
class BasicAuth
|
||||
include Authenticator
|
||||
|
||||
AuthScheme = "Basic"
|
||||
AuthScheme = "Basic" # :nodoc:
|
||||
|
||||
##
|
||||
# Used by UserDB to create a basic password entry
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
attr_accessor :filename
|
||||
attr_accessor :keep_alive
|
||||
attr_reader :config, :sent_size
|
||||
##
|
||||
# Request method for this response
|
||||
|
||||
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)
|
||||
@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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
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
|
||||
|
||||
##
|
||||
# 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue