# Show directory listing?
var show_directory_listing = true is writable
+ # Default file returned when no static file matches the requested URI.
+ #
+ # If no `default_file` is provided, the FileServer responds 404 error to
+ # unmatched queries.
+ var default_file: nullable String = null is writable
+
redef fun answer(request, turi)
do
var response
# This make sure that the requested file is within the root folder.
if (local_file + "/").has_prefix(root) then
# Does it exists?
- if local_file.file_exists then
- if local_file.file_stat.is_dir then
+ var file_stat = local_file.file_stat
+ if file_stat != null then
+ if file_stat.is_dir then
# If we target a directory without an ending `/`,
# redirect to the directory ending with `/`.
- if not request.uri.is_empty and
- request.uri.chars.last != '/' then
- response = new HttpResponse(303)
- response.header["Location"] = request.uri + "/"
- return response
+ var uri = request.uri
+ if not uri.is_empty and uri.chars.last != '/' then
+ return answer_redirection(request.uri + "/")
end
# Show index file instead of the directory listing
end
end
- var is_dir = local_file.file_stat.is_dir
- if show_directory_listing and is_dir then
- # Show the directory listing
- var title = turi
- var files = local_file.files
-
- alpha_comparator.sort files
-
- var links = new Array[String]
- if turi.length > 1 then
- var path = (request.uri + "/..").simplify_path
- links.add "<a href=\"{path}/\">..</a>"
- end
- for file in files do
- var local_path = local_file.join_path(file).simplify_path
- var web_path = file.simplify_path
- if local_path.file_stat.is_dir then web_path = web_path + "/"
- links.add "<a href=\"{web_path}\">{file}</a>"
- end
-
- var header = self.header
- var header_code
- if header != null then
- header_code = header.write_to_string
- else header_code = ""
-
- response = new HttpResponse(200)
- response.body = """
-<!DOCTYPE html>
-<head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
- <script>
- {{{javascript_header or else ""}}}
- </script>
- <title>{{{title}}}</title>
-</head>
-<body>
- {{{header_code}}}
- <div class="container">
- <h1>{{{title}}}</h1>
- <ul>
- <li>{{{links.join("</li>\n\t\t\t<li>")}}}</li>
- </ul>
- </div>
-</body>
-</html>"""
-
- response.header["Content-Type"] = media_types["html"].as(not null)
- else if not is_dir then # It's a single file
+ file_stat = local_file.file_stat
+ if show_directory_listing and file_stat != null and file_stat.is_dir then
+ response = answer_directory_listing(request, turi, local_file)
+ else if file_stat != null and not file_stat.is_dir then # It's a single file
response = answer_file(local_file)
- else response = new HttpResponse(404)
- else response = new HttpResponse(404)
+ else response = answer_default
+ else response = answer_default
else response = new HttpResponse(403)
if response.status_code != 200 then
var tmpl = error_page(response.status_code)
if header != null and tmpl isa ErrorTemplate then tmpl.header = header
- response.body = tmpl.to_s
+ response.body = tmpl
end
return response
end
+ # Answer the `default_file` if any.
+ fun answer_default: HttpResponse do
+ var default_file = self.default_file
+ if default_file == null then
+ return new HttpResponse(404)
+ end
+
+ var local_file = (root / default_file).simplify_path
+ return answer_file(local_file)
+ end
+
+ # Answer a 303 redirection to `location`.
+ fun answer_redirection(location: String): HttpResponse do
+ var response = new HttpResponse(303)
+ response.header["Location"] = location
+ return response
+ end
+
# Build a reponse containing a single `local_file`.
#
# Returns a 404 error if local_file does not exists.
response.header["cache-control"] = cache_control
return response
end
+
+ # Answer with a directory listing for files within `local_files`.
+ fun answer_directory_listing(request: HttpRequest, turi, local_file: String): HttpResponse do
+ # Show the directory listing
+ var title = turi
+ var files = local_file.files
+
+ alpha_comparator.sort files
+
+ var links = new Array[String]
+ if turi.length > 1 then
+ var path = (request.uri + "/..").simplify_path
+ links.add "<a href=\"{path}/\">..</a>"
+ end
+ for file in files do
+ var local_path = local_file.join_path(file).simplify_path
+ var web_path = file.simplify_path
+ var file_stat = local_path.file_stat
+ if file_stat != null and file_stat.is_dir then web_path = web_path + "/"
+ links.add "<a href=\"{web_path}\">{file}</a>"
+ end
+
+ var header = self.header
+ var header_code
+ if header != null then
+ header_code = header.write_to_string
+ else header_code = ""
+
+ var response = new HttpResponse(200)
+ response.body = """
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
+ <script>
+ {{{javascript_header or else ""}}}
+ </script>
+ <title>{{{title}}}</title>
+</head>
+<body>
+ {{{header_code}}}
+ <div class="container">
+ <h1>{{{title}}}</h1>
+ <ul>
+ <li>{{{links.join("</li>\n\t\t\t<li>")}}}</li>
+ </ul>
+ </div>
+</body>
+</html>"""
+
+ response.header["Content-Type"] = media_types["html"].as(not null)
+ return response
+ end
end