mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/webrick/config.rb (WEBrick::Config::General): add default values:
- WEBrick::Config[:DoNotReverseLookup] - WEBrick::Config[:RequestCallback] (it used as an alias of :RequestHandler in WEBrick::HTTPServer#run) - WEBrick::Config::FileHandler[:AcceptableLanguages] * lib/webrick/httpservlet/filehandler.rb (WEBrick::HTTPServlet::FileHandler#set_filename): search files having suffix of language-name which Accept-Language header field includes if :AcceptableLanguages options is present. * lib/webrick/httpservlet/filehandler.rb (WEBrick::HTTPServlet::FileHandler#get_servlet): new method to search servlet correspond to the suffix of filename. * lib/webrick/httprequest.rb: add attributes access methods: accept, accept_charset, accept_encoding, accept_language, content_length and content_type. * lib/webrick/httpresponse.rb: add attribute access methods: content_length, content_length=, content_type and content_type=. * lib/webrick/httputils.rb (WEBrick::HTTPUtils.mime_types): use the second suffix to detect media type. (the first suffix may be a language name.) * lib/webrick/httputils.rb (WEBrick::HTTPUtils.parse_qvalues): add method to parse Accept header field. it returns an Array of values sorted by the qvalues. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@7056 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f93f318f77
commit
a79c87e333
6 changed files with 175 additions and 34 deletions
32
ChangeLog
32
ChangeLog
|
@ -1,3 +1,35 @@
|
||||||
|
Mon Oct 18 02:11:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
|
* lib/webrick/config.rb (WEBrick::Config::General): add default values:
|
||||||
|
- WEBrick::Config[:DoNotReverseLookup]
|
||||||
|
- WEBrick::Config[:RequestCallback] (it used as an alias of
|
||||||
|
:RequestHandler in WEBrick::HTTPServer#run)
|
||||||
|
- WEBrick::Config::FileHandler[:AcceptableLanguages]
|
||||||
|
|
||||||
|
* lib/webrick/httpservlet/filehandler.rb
|
||||||
|
(WEBrick::HTTPServlet::FileHandler#set_filename): search files
|
||||||
|
having suffix of language-name which Accept-Language header field
|
||||||
|
includes if :AcceptableLanguages options is present.
|
||||||
|
|
||||||
|
* lib/webrick/httpservlet/filehandler.rb
|
||||||
|
(WEBrick::HTTPServlet::FileHandler#get_servlet): new method to
|
||||||
|
search servlet correspond to the suffix of filename.
|
||||||
|
|
||||||
|
* lib/webrick/httprequest.rb: add attributes access methods: accept,
|
||||||
|
accept_charset, accept_encoding, accept_language, content_length
|
||||||
|
and content_type.
|
||||||
|
|
||||||
|
* lib/webrick/httpresponse.rb: add attribute access methods:
|
||||||
|
content_length, content_length=, content_type and content_type=.
|
||||||
|
|
||||||
|
* lib/webrick/httputils.rb (WEBrick::HTTPUtils.mime_types):
|
||||||
|
use the second suffix to detect media type. (the first suffix
|
||||||
|
may be a language name.)
|
||||||
|
|
||||||
|
* lib/webrick/httputils.rb (WEBrick::HTTPUtils.parse_qvalues):
|
||||||
|
add method to parse Accept header field. it returns an Array of
|
||||||
|
values sorted by the qvalues.
|
||||||
|
|
||||||
Mon Oct 18 02:04:11 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
Mon Oct 18 02:04:11 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
* lib/webrick/httpserver.rb (WEBrick::HTTPServer#virtual_host): new
|
* lib/webrick/httpserver.rb (WEBrick::HTTPServer#virtual_host): new
|
||||||
|
|
|
@ -33,6 +33,7 @@ module WEBrick
|
||||||
:StartCallback => nil,
|
:StartCallback => nil,
|
||||||
:StopCallback => nil,
|
:StopCallback => nil,
|
||||||
:AcceptCallback => nil,
|
:AcceptCallback => nil,
|
||||||
|
:DoNotReverseLookup => nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
# for HTTPServer, HTTPRequest, HTTPResponse ...
|
# for HTTPServer, HTTPRequest, HTTPResponse ...
|
||||||
|
@ -45,14 +46,15 @@ module WEBrick
|
||||||
:DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
|
:DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
|
||||||
:DocumentRoot => nil,
|
:DocumentRoot => nil,
|
||||||
:DocumentRootOptions => { :FancyIndexing => true },
|
:DocumentRootOptions => { :FancyIndexing => true },
|
||||||
|
|
||||||
:RequestHandler => nil,
|
:RequestHandler => nil,
|
||||||
|
:RequestCallback => nil, # alias of :RequestHandler
|
||||||
|
:ServerAlias => nil,
|
||||||
|
|
||||||
|
# for HTTPProxyServer
|
||||||
:ProxyAuthProc => nil,
|
:ProxyAuthProc => nil,
|
||||||
:ProxyContentHandler => nil,
|
:ProxyContentHandler => nil,
|
||||||
:ProxyVia => true,
|
:ProxyVia => true,
|
||||||
:ProxyTimeout => true,
|
:ProxyTimeout => true,
|
||||||
|
|
||||||
# upstream proxy server
|
|
||||||
:ProxyURI => nil,
|
:ProxyURI => nil,
|
||||||
|
|
||||||
:CGIInterpreter => nil,
|
:CGIInterpreter => nil,
|
||||||
|
@ -71,6 +73,7 @@ module WEBrick
|
||||||
:DirectoryCallback => nil,
|
:DirectoryCallback => nil,
|
||||||
:FileCallback => nil,
|
:FileCallback => nil,
|
||||||
:UserDir => "public_html",
|
:UserDir => "public_html",
|
||||||
|
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicAuth = {
|
BasicAuth = {
|
||||||
|
|
|
@ -32,6 +32,8 @@ module WEBrick
|
||||||
|
|
||||||
# Header and entity body
|
# Header and entity body
|
||||||
attr_reader :raw_header, :header, :cookies
|
attr_reader :raw_header, :header, :cookies
|
||||||
|
attr_reader :accept, :accept_charset
|
||||||
|
attr_reader :accept_encoding, :accept_language
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
attr_accessor :user
|
attr_accessor :user
|
||||||
|
@ -56,6 +58,10 @@ module WEBrick
|
||||||
@raw_header = Array.new
|
@raw_header = Array.new
|
||||||
@header = nil
|
@header = nil
|
||||||
@cookies = []
|
@cookies = []
|
||||||
|
@accept = []
|
||||||
|
@accept_charset = []
|
||||||
|
@accept_encoding = []
|
||||||
|
@accept_language = []
|
||||||
@body = ""
|
@body = ""
|
||||||
|
|
||||||
@addr = @peeraddr = nil
|
@addr = @peeraddr = nil
|
||||||
|
@ -83,6 +89,10 @@ module WEBrick
|
||||||
@header['cookie'].each{|cookie|
|
@header['cookie'].each{|cookie|
|
||||||
@cookies += Cookie::parse(cookie)
|
@cookies += Cookie::parse(cookie)
|
||||||
}
|
}
|
||||||
|
@accept = HTTPUtils.parse_qvalues(self['accept'])
|
||||||
|
@accept_charset = HTTPUtils.parse_qvalues(self['accept-charset'])
|
||||||
|
@accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding'])
|
||||||
|
@accept_language = HTTPUtils.parse_qvalues(self['accept-language'])
|
||||||
end
|
end
|
||||||
return if @request_method == "CONNECT"
|
return if @request_method == "CONNECT"
|
||||||
return if @unparsed_uri == "*"
|
return if @unparsed_uri == "*"
|
||||||
|
@ -124,6 +134,14 @@ module WEBrick
|
||||||
@query
|
@query
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def content_length
|
||||||
|
return Integer(self['content-length'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_type
|
||||||
|
return self['content-type']
|
||||||
|
end
|
||||||
|
|
||||||
def [](header_name)
|
def [](header_name)
|
||||||
if @header
|
if @header
|
||||||
value = @header[header_name.downcase]
|
value = @header[header_name.downcase]
|
||||||
|
|
|
@ -63,6 +63,24 @@ module WEBrick
|
||||||
@header[field.downcase] = value.to_s
|
@header[field.downcase] = value.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def content_length
|
||||||
|
if len = self['content-length']
|
||||||
|
return Integer(len)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_length=(len)
|
||||||
|
self['content-length'] = len.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_type
|
||||||
|
self['content-type']
|
||||||
|
end
|
||||||
|
|
||||||
|
def content_type=(type)
|
||||||
|
self['content-type'] = type
|
||||||
|
end
|
||||||
|
|
||||||
def each
|
def each
|
||||||
@header.each{|k, v| yield(k, v) }
|
@header.each{|k, v| yield(k, v) }
|
||||||
end
|
end
|
||||||
|
@ -250,7 +268,7 @@ module WEBrick
|
||||||
_write_data(socket, "0#{CRLF}#{CRLF}")
|
_write_data(socket, "0#{CRLF}#{CRLF}")
|
||||||
else
|
else
|
||||||
size = @header['content-length'].to_i
|
size = @header['content-length'].to_i
|
||||||
_send_file(socket, @body, 0, size.to_i)
|
_send_file(socket, @body, 0, size)
|
||||||
@sent_size = size
|
@sent_size = size
|
||||||
end
|
end
|
||||||
@body.close
|
@body.close
|
||||||
|
|
|
@ -126,7 +126,7 @@ module WEBrick
|
||||||
end
|
end
|
||||||
|
|
||||||
class FileHandler < AbstractServlet
|
class FileHandler < AbstractServlet
|
||||||
HandlerTable = Hash.new(DefaultFileHandler)
|
HandlerTable = Hash.new
|
||||||
|
|
||||||
def self.add_handler(suffix, handler)
|
def self.add_handler(suffix, handler)
|
||||||
HandlerTable[suffix] = handler
|
HandlerTable[suffix] = handler
|
||||||
|
@ -201,8 +201,7 @@ module WEBrick
|
||||||
def exec_handler(req, res)
|
def exec_handler(req, res)
|
||||||
raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
|
raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
|
||||||
if set_filename(req, res)
|
if set_filename(req, res)
|
||||||
suffix = (/\.(\w+)$/ =~ res.filename) && $1
|
handler = get_handler(req)
|
||||||
handler = @options[:HandlerTable][suffix] || HandlerTable[suffix]
|
|
||||||
call_callback(:HandlerCallback, req, res)
|
call_callback(:HandlerCallback, req, res)
|
||||||
h = handler.get_instance(@config, res.filename)
|
h = handler.get_instance(@config, res.filename)
|
||||||
h.service(req, res)
|
h.service(req, res)
|
||||||
|
@ -212,41 +211,95 @@ module WEBrick
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_handler(req)
|
||||||
|
suffix1 = (/\.(\w+)$/ =~ req.script_name) && $1.downcase
|
||||||
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ req.script_name) && $1.downcase
|
||||||
|
handler_table = @options[:HandlerTable]
|
||||||
|
return handler_table[suffix1] || handler_table[suffix2] ||
|
||||||
|
HandlerTable[suffix1] || HandlerTable[suffix2] ||
|
||||||
|
DefaultFileHandler
|
||||||
|
end
|
||||||
|
|
||||||
def set_filename(req, res)
|
def set_filename(req, res)
|
||||||
handler = nil
|
|
||||||
res.filename = @root.dup
|
res.filename = @root.dup
|
||||||
path_info = req.path_info.scan(%r|/[^/]*|)
|
path_info = req.path_info.scan(%r|/[^/]*|)
|
||||||
|
|
||||||
while name = path_info.shift
|
path_info.unshift("") # dummy for checking @root dir
|
||||||
if name == "/"
|
while base = path_info.first
|
||||||
indices = @config[:DirectoryIndex]
|
check_filename(base)
|
||||||
index = indices.find{|i| FileTest::file?("#{res.filename}/#{i}") }
|
break if base == "/"
|
||||||
name = "/#{index}" if index
|
break unless File.directory?(res.filename + base)
|
||||||
end
|
shift_path_info(req, res, path_info)
|
||||||
res.filename << name
|
call_callback(:DirectoryCallback, req, res)
|
||||||
req.script_name << name
|
end
|
||||||
req.path_info = path_info.join
|
|
||||||
|
|
||||||
if File::fnmatch("/#{@options[:NondisclosureName]}", name)
|
if base = path_info.first
|
||||||
@logger.log(Log::WARN,
|
check_filename(base)
|
||||||
"the request refers nondisclosure name `#{name}'.")
|
if base == "/"
|
||||||
raise HTTPStatus::Forbidden, "`#{req.path}' not found."
|
if file = search_index_file(req, res)
|
||||||
end
|
shift_path_info(req, res, path_info, file)
|
||||||
st = (File::stat(res.filename) rescue nil)
|
call_callback(:FileCallback, req, res)
|
||||||
raise HTTPStatus::NotFound, "`#{req.path}' not found." unless st
|
return true
|
||||||
raise HTTPStatus::Forbidden,
|
end
|
||||||
"no access permission to `#{req.path}'." unless st.readable?
|
shift_path_info(req, res, path_info)
|
||||||
|
elsif file = search_file(req, res, base)
|
||||||
if st.directory?
|
shift_path_info(req, res, path_info, file)
|
||||||
call_callback(:DirectoryCallback, req, res)
|
|
||||||
else
|
|
||||||
call_callback(:FileCallback, req, res)
|
call_callback(:FileCallback, req, res)
|
||||||
return true
|
return true
|
||||||
|
else
|
||||||
|
raise HTTPStatus::NotFound, "`#{req.path}' not found."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_filename(name)
|
||||||
|
if File.fnmatch("/#{@options[:NondisclosureName]}", name)
|
||||||
|
@logger.warn("the request refers nondisclosure name `#{name}'.")
|
||||||
|
raise HTTPStatus::NotFound, "`#{req.path}' not found."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def shift_path_info(req, res, path_info, base=nil)
|
||||||
|
tmp = path_info.shift
|
||||||
|
base = base || tmp
|
||||||
|
req.path_info = path_info.join
|
||||||
|
req.script_name << base
|
||||||
|
res.filename << base
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_index_file(req, res)
|
||||||
|
@config[:DirectoryIndex].each{|index|
|
||||||
|
if file = search_file(req, res, "/"+index)
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_file(req, res, basename)
|
||||||
|
langs = @options[:AcceptableLanguages]
|
||||||
|
path = res.filename + basename
|
||||||
|
if File.file?(path)
|
||||||
|
return basename
|
||||||
|
elsif langs.size > 0
|
||||||
|
req.accept_language.each{|lang|
|
||||||
|
path_with_lang = path + ".#{lang}"
|
||||||
|
if langs.member?(lang) && File.file?(path_with_lang)
|
||||||
|
return basename + ".#{lang}"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
(langs - req.accept_language).each{|lang|
|
||||||
|
path_with_lang = path + ".#{lang}"
|
||||||
|
if File.file?(path_with_lang)
|
||||||
|
return basename + ".#{lang}"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
def call_callback(callback_name, req, res)
|
def call_callback(callback_name, req, res)
|
||||||
if cb = @options[callback_name]
|
if cb = @options[callback_name]
|
||||||
cb.call(req, res)
|
cb.call(req, res)
|
||||||
|
|
|
@ -115,10 +115,9 @@ module WEBrick
|
||||||
module_function :load_mime_types
|
module_function :load_mime_types
|
||||||
|
|
||||||
def mime_type(filename, mime_tab)
|
def mime_type(filename, mime_tab)
|
||||||
if suffix = (/\.(\w+)$/ =~ filename && $1)
|
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
||||||
mtype = mime_tab[suffix.downcase]
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
||||||
end
|
mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
|
||||||
mtype || "application/octet-stream"
|
|
||||||
end
|
end
|
||||||
module_function :mime_type
|
module_function :mime_type
|
||||||
|
|
||||||
|
@ -175,6 +174,24 @@ module WEBrick
|
||||||
end
|
end
|
||||||
module_function :parse_range_header
|
module_function :parse_range_header
|
||||||
|
|
||||||
|
def parse_qvalues(value)
|
||||||
|
tmp = []
|
||||||
|
if value
|
||||||
|
parts = value.split(/,\s*/)
|
||||||
|
parts.each {|part|
|
||||||
|
if m = %r{^([^\s,]+?)(?:;\s*q=([\d]+(?:\.[\d]+)))?$}.match(part)
|
||||||
|
lang = m[1]
|
||||||
|
q = (m[2] or 1).to_f
|
||||||
|
tmp.push([lang, q])
|
||||||
|
end
|
||||||
|
}
|
||||||
|
tmp = tmp.sort_by{|lang, q| -q}
|
||||||
|
tmp.collect!{|lang, q| lang}
|
||||||
|
end
|
||||||
|
return tmp
|
||||||
|
end
|
||||||
|
module_function :parse_qvalues
|
||||||
|
|
||||||
#####
|
#####
|
||||||
|
|
||||||
def dequote(str)
|
def dequote(str)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue