summaryrefslogtreecommitdiff
path: root/lib/webrick/httpservlet/filehandler.rb
diff options
context:
space:
mode:
authorgotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-10-12 12:26:39 +0000
committergotoyuzo <gotoyuzo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-10-12 12:26:39 +0000
commit385edf1e5c6dd5465067bae293844e640e9887a2 (patch)
tree4f7dbe52268e115e7eb879aac99c8b51ab769b90 /lib/webrick/httpservlet/filehandler.rb
parent90b337ce3702db3bf12a9bc13bd36c39ccef9c7e (diff)
* lib/webrick/config.rb:
add 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/trunk@7033 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/webrick/httpservlet/filehandler.rb')
-rw-r--r--lib/webrick/httpservlet/filehandler.rb105
1 files changed, 79 insertions, 26 deletions
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
index ab118ba5c9..1c48734987 100644
--- a/lib/webrick/httpservlet/filehandler.rb
+++ b/lib/webrick/httpservlet/filehandler.rb
@@ -126,7 +126,7 @@ module WEBrick
end
class FileHandler < AbstractServlet
- HandlerTable = Hash.new(DefaultFileHandler)
+ HandlerTable = Hash.new
def self.add_handler(suffix, handler)
HandlerTable[suffix] = handler
@@ -201,8 +201,7 @@ module WEBrick
def exec_handler(req, res)
raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
if set_filename(req, res)
- suffix = (/\.(\w+)$/ =~ res.filename) && $1
- handler = @options[:HandlerTable][suffix] || HandlerTable[suffix]
+ handler = get_handler(req)
call_callback(:HandlerCallback, req, res)
h = handler.get_instance(@config, res.filename)
h.service(req, res)
@@ -212,41 +211,95 @@ module WEBrick
return false
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)
- handler = nil
res.filename = @root.dup
path_info = req.path_info.scan(%r|/[^/]*|)
- while name = path_info.shift
- if name == "/"
- indices = @config[:DirectoryIndex]
- index = indices.find{|i| FileTest::file?("#{res.filename}/#{i}") }
- name = "/#{index}" if index
- end
- res.filename << name
- req.script_name << name
- req.path_info = path_info.join
-
- if File::fnmatch("/#{@options[:NondisclosureName]}", name)
- @logger.log(Log::WARN,
- "the request refers nondisclosure name `#{name}'.")
- raise HTTPStatus::Forbidden, "`#{req.path}' not found."
- end
- st = (File::stat(res.filename) rescue nil)
- raise HTTPStatus::NotFound, "`#{req.path}' not found." unless st
- raise HTTPStatus::Forbidden,
- "no access permission to `#{req.path}'." unless st.readable?
+ path_info.unshift("") # dummy for checking @root dir
+ while base = path_info.first
+ check_filename(base)
+ break if base == "/"
+ break unless File.directory?(res.filename + base)
+ shift_path_info(req, res, path_info)
+ call_callback(:DirectoryCallback, req, res)
+ end
- if st.directory?
- call_callback(:DirectoryCallback, req, res)
- else
+ if base = path_info.first
+ check_filename(base)
+ if base == "/"
+ if file = search_index_file(req, res)
+ shift_path_info(req, res, path_info, file)
+ call_callback(:FileCallback, req, res)
+ return true
+ end
+ shift_path_info(req, res, path_info)
+ elsif file = search_file(req, res, base)
+ shift_path_info(req, res, path_info, file)
call_callback(:FileCallback, req, res)
return true
+ else
+ raise HTTPStatus::NotFound, "`#{req.path}' not found."
end
end
+
return false
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)
if cb = @options[callback_name]
cb.call(req, res)