Class: Ramaze::Dispatcher::File
- Extended by:
- Trinity
- Defined in:
- lib/ramaze/dispatcher/file.rb
Overview
First of the dispatchers, looks up the public path and serves the file if found.
Constant Summary collapse
- INDICES =
These names are checked for serving from public directory. They take priority over Actions which comes later in the FILTER
%w[index.htm index.xhtml index.html index]
Class Method Summary collapse
-
.call(path) ⇒ Object
Entry point from Dispatcher::filter.
-
.in_public?(path) ⇒ Boolean
Determine whether a path is in the public directory for better security.
-
.open_file(path) ⇒ Object
returns file-handle with the open file on success, setting the Content-Type as found in Tool::MIME.
-
.resolve_path(path) ⇒ Object
If path matches a directory in public_root, return that directory path, unless there is an index file in that directory, in which case return path for that.
Class Method Details
.call(path) ⇒ Object
Entry point from Dispatcher::filter. searches for the file and builds a response with status 200 if found.
24 25 26 27 28 29 30 31 |
# File 'lib/ramaze/dispatcher/file.rb', line 24 def call(path) return unless file = open_file(CGI.unescape(path)) Session.current.drop! if Session.current if file == :NotModified return response.build([], STATUS_CODE['Not Modified']) end response.build(file, STATUS_CODE['OK']) end |
.in_public?(path) ⇒ Boolean
Determine whether a path is in the public directory for better security.
75 76 77 |
# File 'lib/ramaze/dispatcher/file.rb', line 75 def in_public?(path) (path).start_with?((Global.public_root)) end |
.open_file(path) ⇒ Object
returns file-handle with the open file on success, setting the Content-Type as found in Tool::MIME
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/ramaze/dispatcher/file.rb', line 36 def open_file(path) file = resolve_path(path) if ::File.file?(file) return unless in_public?(file) response['Content-Type'] = Tool::MIME.type_for(file) unless ::File.extname(file).empty? mtime = ::File.mtime(file) response['Last-Modified'] = mtime.httpdate response['ETag']= Digest::MD5.hexdigest(file+mtime.to_s).inspect if modified_since = request.env['HTTP_IF_MODIFIED_SINCE'] return :NotModified unless Time.parse(modified_since) < mtime elsif match = request.env['HTTP_IF_NONE_MATCH'] # Should be a unique string enclosed in "" # To avoiding more file reading we use mtime and filepath # we could throw in inode and size for more uniqueness return :NotModified if response['ETag']==match end log(file) ::File.open(file, 'rb') end end |
.resolve_path(path) ⇒ Object
If path matches a directory in public_root, return that directory path, unless there is an index file in that directory, in which case return path for that. If path is not a directory, simply return given path in public_root. Either way, the returned path always starts with public_root.
63 64 65 66 67 68 69 70 71 |
# File 'lib/ramaze/dispatcher/file.rb', line 63 def resolve_path(path) joined = ::File.join(Global.public_root, path) if ::File.directory?(joined) Dir[joined/"{#{INDICES.join(',')}}"].first || joined else joined end end |