nitcorn/file_server: extract answer_file method
[nit.git] / lib / nitcorn / file_server.nit
index 3552b2d..f9feb0f 100644 (file)
@@ -60,10 +60,19 @@ class FileServer
        end
 
        # Error page template for a given `code`
-       fun error_page(code: Int): Streamable do return new ErrorTemplate(code)
+       fun error_page(code: Int): Writable do return new ErrorTemplate(code)
 
        # Header of each directory page
-       var header: nullable Streamable = null is writable
+       var header: nullable Writable = null is writable
+
+       # Custom JavaScript code added within a `<script>` block to each page
+       var javascript_header: nullable Writable = null is writable
+
+       # Caching attributes of served files, used as the `cache-control` field in response headers
+       var cache_control = "public, max-age=360" is writable
+
+       # Show directory listing?
+       var show_directory_listing = true is writable
 
        redef fun answer(request, turi)
        do
@@ -99,12 +108,14 @@ class FileServer
                                        end
                                end
 
-                               response = new HttpResponse(200)
-                               if local_file.file_stat.is_dir then
+                               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
@@ -123,12 +134,16 @@ class FileServer
                                                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>
@@ -143,22 +158,9 @@ class FileServer
 </html>"""
 
                                        response.header["Content-Type"] = media_types["html"].as(not null)
-                               else
-                                       # It's a single file
-                                       var file = new IFStream.open(local_file)
-                                       response.body = file.read_all
-
-                                       var ext = local_file.file_extension
-                                       if ext != null then
-                                               var media_type = media_types[ext]
-                                               if media_type != null then
-                                                       response.header["Content-Type"] = media_type
-                                               else response.header["Content-Type"] = "application/octet-stream"
-                                       end
-
-                                       file.close
-                               end
-
+                               else if not 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 = new HttpResponse(403)
 
@@ -170,4 +172,27 @@ class FileServer
 
                return response
        end
+
+       # Build a reponse containing a single `local_file`.
+       #
+       # Returns a 404 error if local_file does not exists.
+       fun answer_file(local_file: String): HttpResponse do
+               if not local_file.file_exists then return new HttpResponse(404)
+
+               var response = new HttpResponse(200)
+               response.files.add local_file
+
+               # Set Content-Type depending on the file extension
+               var ext = local_file.file_extension
+               if ext != null then
+                       var media_type = media_types[ext]
+                       if media_type != null then
+                               response.header["Content-Type"] = media_type
+                       else response.header["Content-Type"] = "application/octet-stream"
+               end
+
+               # Cache control
+               response.header["cache-control"] = cache_control
+               return response
+       end
 end