1
0
Fork 0
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:
drbrain 2013-01-26 01:12:54 +00:00
parent 89232d1dd9
commit 28afe277a8
23 changed files with 839 additions and 85 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,
}

View file

@ -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)

View file

@ -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

View file

@ -34,7 +34,7 @@ module WEBrick
class BasicAuth
include Authenticator
AuthScheme = "Basic"
AuthScheme = "Basic" # :nodoc:
##
# Used by UserDB to create a basic password entry

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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]

View file

@ -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{

View file

@ -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