summaryrefslogtreecommitdiff
path: root/Servers
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-02-12 21:18:04 +0100
committerAndreas Kling <kling@serenityos.org>2020-02-12 21:18:04 +0100
commit083f3edcb00769fa2a0b95ad8d9d2a46e54d3778 (patch)
tree43a315f8f88a94db408c09ede6fbdb35bdd495be /Servers
parent90fec9c7327fcee65bf40342d303641709dca070 (diff)
downloadserenity-083f3edcb00769fa2a0b95ad8d9d2a46e54d3778.zip
WebServer: Add basic directory listings
If a directory does not have an index.html file, we will now generate a directory listing HTML document for that directory on the fly. :^)
Diffstat (limited to 'Servers')
-rw-r--r--Servers/WebServer/Client.cpp65
-rw-r--r--Servers/WebServer/Client.h2
2 files changed, 59 insertions, 8 deletions
diff --git a/Servers/WebServer/Client.cpp b/Servers/WebServer/Client.cpp
index 0114d19559..cd1984478d 100644
--- a/Servers/WebServer/Client.cpp
+++ b/Servers/WebServer/Client.cpp
@@ -28,6 +28,7 @@
#include <AK/FileSystemPath.h>
#include <AK/StringBuilder.h>
#include <LibCore/DateTime.h>
+#include <LibCore/DirIterator.h>
#include <LibCore/File.h>
#include <LibCore/HttpRequest.h>
#include <stdio.h>
@@ -79,22 +80,37 @@ void Client::handle_request(ByteBuffer raw_request)
return;
}
- FileSystemPath canonical_path(request.resource());
- dbg() << "Requested canonical path: '" << canonical_path.string() << "'";
+ auto requested_path = canonicalized_path(request.resource());
+ dbg() << "Canonical requested path: '" << requested_path << "'";
StringBuilder path_builder;
path_builder.append("/www/");
- path_builder.append(canonical_path.string());
-
- if (Core::File::is_directory(path_builder.to_string()))
- path_builder.append("/index.html");
+ path_builder.append(requested_path);
+ auto real_path = path_builder.to_string();
+
+ if (Core::File::is_directory(real_path)) {
+ StringBuilder index_html_path_builder;
+ index_html_path_builder.append(real_path);
+ index_html_path_builder.append("/index.html");
+ auto index_html_path = index_html_path_builder.to_string();
+ if (!Core::File::exists(index_html_path)) {
+ handle_directory_listing(requested_path, real_path, request);
+ return;
+ }
+ real_path = index_html_path;
+ }
- auto file = Core::File::construct(path_builder.to_string());
+ auto file = Core::File::construct(real_path);
if (!file->open(Core::File::ReadOnly)) {
send_error_response(404, "Not found, bro!", request);
return;
}
+ send_response(file->read_all(), request);
+}
+
+void Client::send_response(StringView response, const Core::HttpRequest& request)
+{
StringBuilder builder;
builder.append("HTTP/1.0 200 OK\r\n");
builder.append("Server: WebServer (SerenityOS)\r\n");
@@ -102,11 +118,44 @@ void Client::handle_request(ByteBuffer raw_request)
builder.append("\r\n");
m_socket->write(builder.to_string());
- m_socket->write(file->read_all());
+ m_socket->write(response);
log_response(200, request);
}
+void Client::handle_directory_listing(const String& requested_path, const String& real_path, const Core::HttpRequest& request)
+{
+ StringBuilder builder;
+
+ builder.append("<!DOCTYPE html>\n");
+ builder.append("<html>\n");
+ builder.append("<head><title>Index of ");
+ builder.append(requested_path);
+ builder.append("</title></head>\n");
+ builder.append("<body>\n");
+ builder.append("<h1>Index of ");
+ builder.append(requested_path);
+ builder.append("</h1>\n");
+ builder.append("<ul>\n");
+
+ Core::DirIterator dt(real_path);
+ while (dt.has_next()) {
+ auto name = dt.next_path();
+ builder.append("<li>");
+ builder.append("<a href=\"");
+ builder.append(name);
+ builder.append("\">");
+ builder.append(name);
+ builder.append("</a></li>\n");
+ }
+
+ builder.append("</ul>\n");
+ builder.append("</body>\n");
+ builder.append("</html>\n");
+
+ send_response(builder.to_string(), request);
+}
+
void Client::send_error_response(unsigned code, const StringView& message, const Core::HttpRequest& request)
{
StringBuilder builder;
diff --git a/Servers/WebServer/Client.h b/Servers/WebServer/Client.h
index aa57b17bba..9b0061b133 100644
--- a/Servers/WebServer/Client.h
+++ b/Servers/WebServer/Client.h
@@ -44,9 +44,11 @@ private:
Client(NonnullRefPtr<Core::TCPSocket>, Core::Object* parent);
void handle_request(ByteBuffer);
+ void send_response(StringView, const Core::HttpRequest&);
void send_error_response(unsigned code, const StringView& message, const Core::HttpRequest&);
void die();
void log_response(unsigned code, const Core::HttpRequest&);
+ void handle_directory_listing(const String& requested_path, const String& real_path, const Core::HttpRequest&);
NonnullRefPtr<Core::TCPSocket> m_socket;
};