Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#################################################################################
################################################################################
# Project setup

NAME = webserv
Expand All @@ -19,15 +19,15 @@ SRCS = $(addprefix $(SRC_DIR)/, \
core/server.hpp \
core/signals.cpp \
core/signals.hpp \
handler/static_file_handler.cpp \
handler/static_file_handler.hpp \
handler/handler.cpp \
handler/handler.hpp \
handler/get_handler.cpp \
handler/get_handler.hpp \
http/http_request.hpp \
handler/handler.hpp \
http/http_request.hpp \
http/http_response.cpp \
http/http_response.hpp \
router/router.cpp \
router/router.hpp \
router/router.hpp \
util/syscall_error.cpp \
util/syscall_error.hpp \
main.cpp \
Expand Down Expand Up @@ -80,7 +80,7 @@ fclean: clean

re: fclean all

#################################################################################
################################################################################
# Unit tests

TEST_NAME = run_tests
Expand All @@ -93,7 +93,8 @@ TEST_TARGET = $(BIN_DIR)/$(TEST_NAME)
# All tests sources (keep in alphabetical order)
TEST_SRCS = $(addprefix $(TEST_SRC_DIR)/, \
http_response_unittest.cpp \
router_unittest.cpp \
router_unittest.cpp \
static_file_handler_unittest.cpp \
main.cpp \
)

Expand Down Expand Up @@ -122,7 +123,7 @@ PHONY += test-clean
test-clean:
rm -rf $(TEST_OBJ_DIR) $(TEST_TARGET)

#################################################################################
################################################################################
# Formatting and linting section

# If compiledb is not installed do `pipx install compiledb`.
Expand Down
2 changes: 1 addition & 1 deletion src/core/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ void Server::handle_events(Client* conn, uint32_t events)

// Can write to socket
if (events & EPOLLOUT) {
if (conn->handler()->is_readable()) {
if (conn->handler()->has_output()) {
int n = conn->handler()->read_data(tmp, sizeof(tmp));
if (n > 0)
conn->send_buffer().append(tmp, n);
Expand Down
4 changes: 2 additions & 2 deletions src/handler/handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Handler {
virtual int read_data(char* buf, int n) = 0;
virtual int write_data(const char* buf, int n) = 0;

virtual bool is_readable() const = 0;
virtual bool is_writable() const = 0;
virtual bool has_output() const = 0;
virtual bool needs_input() const = 0;
virtual bool is_done() const = 0;

protected:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "handler/get_handler.hpp"
#include "handler/static_file_handler.hpp"

#include "http/http_response.hpp"
#include "util/syscall_error.hpp"
Expand All @@ -11,7 +11,7 @@
#include <iostream>
#include <sstream>

GetHandler::GetHandler(const std::string& path)
StaticFileHandler::StaticFileHandler(const std::string& path)
: kFilePath(path),
fd_(-1),
file_size_(0),
Expand Down Expand Up @@ -51,13 +51,13 @@ GetHandler::GetHandler(const std::string& path)
headers_ = res.to_string();
}

GetHandler::~GetHandler()
StaticFileHandler::~StaticFileHandler()
{
if (fd_ != -1)
close(fd_);
}

int GetHandler::read_data(char* buf, int n)
int StaticFileHandler::read_data(char* buf, int n)
{
int bytes_written = 0;

Expand Down Expand Up @@ -88,14 +88,14 @@ int GetHandler::read_data(char* buf, int n)
}

// We never write to this handler (read-only)
int GetHandler::write_data(const char* buf, int n)
int StaticFileHandler::write_data(const char* buf, int n)
{
(void) buf;
(void) n;
return 0;
}

const std::string GetHandler::derive_file_type()
const std::string StaticFileHandler::derive_file_type()
{
size_t pos = kFilePath.rfind(".");
if (pos == std::string::npos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,23 @@

#include <string>

class GetHandler : public Handler {
class StaticFileHandler : public Handler {
public:
explicit GetHandler(const std::string& path);
virtual ~GetHandler();
explicit StaticFileHandler(const std::string& path);
virtual ~StaticFileHandler();

virtual int read_data(char* buf, int n);
virtual int write_data(const char* buf, int n);

virtual bool is_readable() const { return !is_done(); } // read until done
virtual bool is_writable() const { return false; }; // handler is read-only
virtual bool is_done() const
{
return (has_body() && body_sent()) || (!has_body() && headers_sent());
};
virtual bool has_output() const { return !headers_sent() || (has_body() && !body_sent()); }
virtual bool needs_input() const { return false; };
virtual bool is_done() const { return !has_output(); }

const std::string kFilePath;

private:
GetHandler(const GetHandler&);
GetHandler& operator=(const GetHandler&);
StaticFileHandler(const StaticFileHandler&);
StaticFileHandler& operator=(const StaticFileHandler&);

bool has_body() const { return fd_ != -1; }
bool headers_sent() const { return headers_off_ == headers_.size(); }
Expand Down
5 changes: 2 additions & 3 deletions src/router/router.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include "router/router.hpp"

#include "config/server_config.hpp"
#include "core/client.hpp"
#include "handler/get_handler.hpp"
#include "handler/static_file_handler.hpp"
#include "http/http_request.hpp"

#include <sys/stat.h>
Expand Down Expand Up @@ -98,7 +97,7 @@ Handler* Router::handle_request(const HttpRequest& request)
}
std::string full_path = build_request_path(request, longest_match);
if (request.method == "GET") {
return new GetHandler(full_path);
return new StaticFileHandler(full_path);
}

// Add other handlers here
Expand Down
72 changes: 72 additions & 0 deletions tests/static_file_handler_unittest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "handler/static_file_handler.hpp"
#include "utest/utest.h"

#include <iostream>

// NOTE(isma): Might not be the best idea to hardcode these responses because
// the order of headers will likely change. If any of these tests fail, feel
// free to skip them until the HTTP response design is more stable.

UTEST(GetHandlerTest, StatusOk)
{
char buf[4096] = {0};
StaticFileHandler test("www/example/index.html");

test.read_data(buf, sizeof(buf));

ASSERT_STREQ(buf, "HTTP/1.1 200 OK\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 64\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!DOCTYPE html><html><head><title>Example</title></head></html>\n");
}

UTEST(GetHandlerTest, StatusNotFound)
{
char buf[4096] = {0};
StaticFileHandler test("www/example/inexistant.html");

test.read_data(buf, sizeof(buf));

ASSERT_STREQ(buf, "HTTP/1.1 404 Not Found\r\n\r\n");
}

UTEST(GetHandlerTest, ReadSomeData)
{
char buf[4096] = {0};
StaticFileHandler test("");

EXPECT_TRUE(test.has_output());
EXPECT_FALSE(test.needs_input());
ASSERT_TRUE(test.read_data(buf, sizeof(buf)));
}

UTEST(GetHandlerTest, WriteNoData)
{
char msg[] = "Hello, world!\n";
StaticFileHandler test("");

EXPECT_TRUE(test.has_output());
EXPECT_FALSE(test.needs_input());
ASSERT_FALSE(test.write_data(msg, sizeof(msg)));
}

UTEST(GetHandlerTest, SmallBuffer)
{
char buf[1] = {0};
StaticFileHandler test("www/example/index.html");

std::string res;

while (test.read_data(buf, sizeof(buf)) > 0) {
res.append(buf, 1);
}

ASSERT_STREQ(res.c_str(), "HTTP/1.1 200 OK\r\n"
"Connection: keep-alive\r\n"
"Content-Length: 64\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!DOCTYPE html><html><head><title>Example</title></head></html>\n");
}
1 change: 1 addition & 0 deletions www/example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!DOCTYPE html><html><head><title>Example</title></head></html>