class Middleware
A middleware which serves static files from the specified root directory.
Definitions
def initialize(app, root: Utopia::default_root, types: MIME_TYPES[:default], cache_control: DEFAULT_CACHE_CONTROL)
Implementation
def initialize(app, root: Utopia::default_root, types: MIME_TYPES[:default], cache_control: DEFAULT_CACHE_CONTROL)
@app = app
@root = root
@extensions = MimeTypeLoader.extensions_for(types)
@cache_control = cache_control
end
def freeze
Freeze this object and its internal state.
Signature
-
returns
self This object.
Implementation
def freeze
return self if frozen?
@root.freeze
@extensions.freeze
@cache_control.freeze
super
end
def fetch_file(path)
Open metadata for an existing file under the static root.
Signature
-
parameter
pathUtopia::Path | String The path.
-
returns
LocalFile | Nil The local file, or
nilwhen it does not exist.
Implementation
def fetch_file(path)
# We need file_path to be an absolute path for X-Sendfile to work correctly.
file_path = File.join(@root, path.components)
if File.exist?(file_path)
return LocalFile.new(@root, path)
else
return nil
end
end
def response_headers_for(file, content_type)
Build response headers for the given file.
Signature
-
parameter
fileLocalFile The file.
-
parameter
content_typeString The content type.
-
returns
Hash(String, String) The response headers.
Implementation
def response_headers_for(file, content_type)
if @cache_control.respond_to?(:call)
cache_control = @cache_control.call(file)
else
cache_control = @cache_control
end
{
LAST_MODIFIED => file.mtime_date,
CONTENT_TYPE => content_type,
CACHE_CONTROL => cache_control,
ETAG => file.etag,
ACCEPT_RANGES => "bytes"
}
end
def respond(env, path_info, extension)
Serve a static file for the requested path and extension.
Signature
-
parameter
envHash The Rack environment.
-
parameter
path_infoString The request path.
-
parameter
extensionString The file extension.
-
returns
Array | Nil The Rack response when a file is found.
Implementation
def respond(env, path_info, extension)
path = Path[path_info].simplify
if locale = env[Localization::CURRENT_LOCALE_KEY]
path.last.insert(path.last.rindex(".") || -1, ".#{locale}")
end
if file = fetch_file(path)
response_headers = self.response_headers_for(file, @extensions[extension])
if file.modified?(env)
return file.serve(env, response_headers)
else
return [304, response_headers, []]
end
end
end
def call(env)
Serve a recognized static file or pass the request downstream.
Signature
-
parameter
envHash The Rack environment.
-
returns
Array The static-file or downstream Rack response.
Implementation
def call(env)
path_info = env[Rack::PATH_INFO]
extension = File.extname(path_info)
if @extensions.key?(extension.downcase)
if response = self.respond(env, path_info, extension)
return response
end
end
# else if no file was found:
return @app.call(env)
end