diff --git a/.gitignore b/httpd/.gitignore similarity index 70% rename from .gitignore rename to httpd/.gitignore index 85e1c00..a20dfd8 100644 --- a/.gitignore +++ b/httpd/.gitignore @@ -6,5 +6,3 @@ *.log *.core httpd -__pycache__ -env/ diff --git a/Makefile b/httpd/Makefile similarity index 78% rename from Makefile rename to httpd/Makefile index 0682316..70108ef 100644 --- a/Makefile +++ b/httpd/Makefile @@ -31,14 +31,8 @@ TARGET=httpd $(TARGET): $(OBJS) $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS) -check: $(TARGET) - cp $(TARGET) tests/$(TARGET) - cd tests - python3 -m venv env - env/bin/python -m pip install requests - env/bin/python -m pip install pytest - env/bin/python -m pip install pytest-timeout - - env/bin/pytest +check: + dash tests/run.sh debug: CFLAGS += $(CFLAGS_DBG) debug: $(OBJS) @@ -51,7 +45,5 @@ asan: $(OBJS) $(CC) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LDLIBS) clean: - - pkill -9 $(TARGET) - $(RM) tests/$(TARGET) tests/out.log $(RM) $(TARGET) $(RM) $(OBJS) diff --git a/tests/config.txt b/httpd/config.txt similarity index 90% rename from tests/config.txt rename to httpd/config.txt index 77d4974..239d20d 100644 --- a/tests/config.txt +++ b/httpd/config.txt @@ -1,7 +1,6 @@ [global] log = true pid_file = /tmp/HTTPd.pid -daemon = start [[vhosts]] server_name = my_server diff --git a/tests/config_reader.sh b/httpd/config_reader.sh similarity index 100% rename from tests/config_reader.sh rename to httpd/config_reader.sh diff --git a/src/config/config.c b/httpd/src/config/config.c similarity index 90% rename from src/config/config.c rename to httpd/src/config/config.c index c8edde6..d910424 100644 --- a/src/config/config.c +++ b/httpd/src/config/config.c @@ -5,8 +5,8 @@ #include #include -// #include "../utils/string/string.h" -// #include "bits/getopt_ext.h" +#include "../utils/string/string.h" +#include "bits/getopt_ext.h" #define ARG_VALID 0 #define ARG_INVALID 1 @@ -180,19 +180,6 @@ static void print_arg_error(int err, char **argv, struct option options[], } } -// static void apply_default_values(struct config *cfg) -// { -// // Default file -// if (cfg->servers->default_file == NULL) -// { -// char *default_df = DEFAULT_DF; -// cfg->servers->default_file = -// malloc((strlen(default_df) + 1) * sizeof(char)); -// // TODO handle error -// strcpy(cfg->servers->default_file, default_df); -// } -// } - // == Main functions struct config *parse_configuration(int argc, char *argv[]) @@ -240,12 +227,10 @@ struct config *parse_configuration(int argc, char *argv[]) } } - // apply_default_values(config); - // Check config validity if (check_config(config) != 0) { - printf("%s: Missing mandatory flags, cannot continue.\n", argv[0]); + printf("%s: Missing mandatory flags, cannot continue.", argv[0]); config_destroy(config); return NULL; } diff --git a/src/config/config.h b/httpd/src/config/config.h similarity index 94% rename from src/config/config.h rename to httpd/src/config/config.h index 72be5a8..5caf4ac 100644 --- a/src/config/config.h +++ b/httpd/src/config/config.h @@ -6,9 +6,6 @@ #include -// Default values -#define DEFAULT_DF "index.html" - /* ** @brief Enum daemon ** NO_OPTION if the '--daemon' option is not given @@ -36,7 +33,7 @@ struct config char *pid_file; char *log_file; bool log; - char *protocol_version; + char* protocol_version; struct server_config *servers; enum daemon daemon; diff --git a/src/daemon/daemon.c b/httpd/src/daemon/daemon.c similarity index 69% rename from src/daemon/daemon.c rename to httpd/src/daemon/daemon.c index a918966..0d5f52e 100644 --- a/src/daemon/daemon.c +++ b/httpd/src/daemon/daemon.c @@ -3,10 +3,8 @@ #include #include #include -#include #include "../server/server.h" -#include "../utils/files/files.h" static struct config *config; @@ -17,7 +15,7 @@ void daemon_init(struct config *cfg) config = cfg; } -int get_pid(void) +int get_pid() { FILE *stream = fopen(config->pid_file, "r"); if (stream == NULL) @@ -45,21 +43,7 @@ void stop_daemon(void) int start_daemon(void) { - pid_t pid = fork(); - if (!pid) // Daemon - { - start_server(config); - } - else // Parent - { - // Write pid - int err = write_pid(config->pid_file, pid); - if (err != 0) - { - kill(pid, SIGINT); - return 1; - } - } + start_server("localhost", config->servers->port); return 0; } diff --git a/src/daemon/daemon.h b/httpd/src/daemon/daemon.h similarity index 82% rename from src/daemon/daemon.h rename to httpd/src/daemon/daemon.h index f1dcae8..dff31d9 100644 --- a/src/daemon/daemon.h +++ b/httpd/src/daemon/daemon.h @@ -7,11 +7,11 @@ * * @return */ -int get_pid(void); +int get_pid(); /* @brief */ -void daemon_init(struct config *cfg); +void daemon_init(struct config* cfg); /* @brief */ diff --git a/src/http/headers.c b/httpd/src/http/headers.c similarity index 83% rename from src/http/headers.c rename to httpd/src/http/headers.c index ce7806c..5463d92 100644 --- a/src/http/headers.c +++ b/httpd/src/http/headers.c @@ -5,15 +5,12 @@ #include #include "../utils/parsing/words.h" -#include "../utils/string/string.h" void destroy_headers(struct http_header *headers) { while (headers != NULL) { struct http_header *next = headers->next; - string_destroy(headers->field); - string_destroy(headers->value); free(headers); headers = next; } @@ -42,12 +39,6 @@ ssize_t read_value(struct string *str, size_t offset, struct string **res) if (str->size <= offset + nread || str->data[offset + nread] != '\n') return ERR_HTTP_INVALID_INPUT; - // Trim trailing \r - if ((*res)->size > 0 && (*res)->data[(*res)->size - 1] == '\r') - { - (*res)->size--; - } - return nread; } @@ -59,8 +50,7 @@ ssize_t parse_headers(struct http_request *res, struct string *req, // Yes I know I do one useless allocation but I really don't care at this // point - while (i < req->size && req->data[i] != '\n' - && req->data[i] != '\r') // ! Blank line + while (req->data[i] != '\n') // ! Blank line { if (header == NULL) { @@ -80,26 +70,21 @@ ssize_t parse_headers(struct http_request *res, struct string *req, return ERR_HTTP_OUT_OF_MEMORY; // Read field - ssize_t nread = read_field(req, i, &header->field); + ssize_t nread = read_field(req, offset, &header->field); if (nread <= 0) return nread; // Contains error code when negative - i += nread + 1; + i += nread; // Read value - nread = read_value(req, i, &header->value); + nread = read_value(req, offset, &header->value); if (nread <= 0) return nread; // Contains error code when negative i += nread + 1; } - if (i < req->size && req->data[i] == '\r') - i++; - if (i < req->size && req->data[i] == '\n') - i++; - - return i; + return i + 1; } struct http_header *get_header(struct http_header *headers, const char *field) diff --git a/src/http/headers.h b/httpd/src/http/headers.h similarity index 86% rename from src/http/headers.h rename to httpd/src/http/headers.h index 460cd3e..59592de 100644 --- a/src/http/headers.h +++ b/httpd/src/http/headers.h @@ -57,7 +57,7 @@ ssize_t parse_headers(struct http_request *res, struct string *req, * * @return */ -struct http_header *get_header(struct http_header *headers, const char *field); +struct http_header* get_header(struct http_header *headers, const char* field); /* * @brief @@ -67,7 +67,7 @@ struct http_header *get_header(struct http_header *headers, const char *field); * * @return */ -struct http_header *create_header(const char *field, const char *value); +struct http_header* create_header(const char* field, const char* value); /* * @brief diff --git a/src/http/http.c b/httpd/src/http/http.c similarity index 62% rename from src/http/http.c rename to httpd/src/http/http.c index 4fb2280..8977ee0 100644 --- a/src/http/http.c +++ b/httpd/src/http/http.c @@ -2,14 +2,13 @@ #include #include -// #include +#include #include #include #include #include #include -#include "../config/config.h" #include "../logger/logs.h" #include "../utils/files/files.h" #include "../utils/parsing/words.h" @@ -31,16 +30,16 @@ static ssize_t parse_reqline(struct http_request *res, struct string *req) ssize_t i = 0; ssize_t skipped; - if (res == NULL || req == NULL) + if (res == NULL) return ERR_HTTP_INTERNAL_ERROR; // Method - if (string_compare_n_str(req, "GET", strlen("GET")) == 0) + if (strncmp(req->data, "GET", strlen("GET")) == 0) { res->method = GET; i += strlen("GET"); } - else if (string_compare_n_str(req, "HEAD", strlen("HEAD")) == 0) + else if (strncmp(req->data, "HEAD", strlen("HEAD")) == 0) { res->method = HEAD; i += strlen("HEAD"); @@ -68,15 +67,9 @@ static ssize_t parse_reqline(struct http_request *res, struct string *req) return ERR_HTTP_INVALID_INPUT; i += skipped; - // CRLF (EOL) oh qu'il est casse couilles celui-là - ssize_t req_size = req->size; // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah - if (i < req_size && req->data[i] == '\r') - i++; - if (i >= req_size || req->data[i] != '\n') + // CRLF (EOL) + if (req->data[i++] != '\r' && req->data[i++] != '\n') return ERR_HTTP_INVALID_INPUT; - i++; - // Donc 2h de debug pour ça là ? Plutot envie de me tirer une balle si vous - // voulez mon avis return i; } @@ -98,34 +91,25 @@ static void split_target(struct http_request *req) } } -// Finds a valid path based on the client input and returns the corresponding -// FILES return value (see files.h) -static int find_target(struct http_request *req) +// Finds a valid path based on the client input +static bool find_target(struct http_request *req) { // Check filename if (!check_filename(req->target)) - return ERR_FILES_FORBIDDEN; - - char *target = string_to_charptr(req->target); - int err = is_directory(target); - free(target); - - if (err == FILES_DIR) // Is a directory + return false; + int err = is_directory(req->target->data); + if (err == -1) + return false; + else if (err == 1) { - // Append default file if directory if (req->target->data[req->target->size - 1] != '/') string_concat_str(req->target, "/", 1); string_concat_str(req->target, config->servers->default_file, strlen(config->servers->default_file)); - // Recheck - target = string_to_charptr(req->target); - err = is_directory(target); - free(target); - return err; } - return err; + return true; } // WARNING allocates result on the heap @@ -176,51 +160,6 @@ static struct string *generate_status_message(int status_code) return string_create(message, strlen(message)); } -static void check_req(struct http_request *req, struct http_response *resp) -{ - // Method - if (req->method == INVALID_METHOD) - resp->status_code = 405; - - // Protocol - // Oui il y a plus beau, mais on a le temps ou on l'a pas, moi je l'ai pas, - // alors si t'es pas content t'as qu'à le modifier toi même vu que tu as - // visiblement le code source. <3 - if (string_compare_strictly_n_str(req->protocol, "HTTP/", strlen("HTTP/")) - != 0) - resp->status_code = 400; - else if (string_compare_strictly_n_str(req->protocol, "HTTP/1.1", - strlen("HTTP/1.1")) - != 0) - resp->status_code = 505; - - // Host - if (resp->status_code != 400 && resp->status_code != 505) - { - int host_count = 0; - struct http_header *cur = req->headers; - while (cur != NULL) - { - if (cur->field->size == 4 - && string_compare_n_str(cur->field, "host", 4) == 0) - { - host_count++; - if (cur->value == NULL || cur->value->size == 0) - { - resp->status_code = 400; - break; - } - } - cur = cur->next; - } - - if (host_count != 1) - resp->status_code = 400; - } - - // printf("%s %d\n", req->protocol->data, resp->status_code); -} - // === Functions void http_init(struct config *cfg) @@ -229,7 +168,7 @@ void http_init(struct config *cfg) } // TODO handle logs -void handle_request(int client_fd, char *client_ip) +void handle_request(int client_fd) { char buffer[BUFFER_SIZE]; // Declared in server.h struct string *str = string_create(NULL, 0); @@ -246,39 +185,27 @@ void handle_request(int client_fd, char *client_ip) { string_concat_str(str, buffer, nread); } - if (nread > 0) - string_concat_str(str, buffer, nread); + string_concat_str(str, buffer, nread); // Parse request struct http_request *req = parse_request(str); if (req == NULL) - { - free(str); return; - } char *method = get_http_method(req->method); char *target = string_to_charptr(req->target); - print_log_request(method, target, client_ip); + log_request(method, target, "127.0.0.1"); free(method); free(target); // Generate response struct http_response *resp = generate_response(req); if (resp == NULL) - { - free(str); - free(req); return; - } // Format response to string struct string *res = format_response(resp); if (res == NULL) - { - free(str); - free(req); return; - } // Send response ssize_t nsent; @@ -301,18 +228,8 @@ void handle_request(int client_fd, char *client_ip) int fd = open(target, O_RDONLY); if (fd > 0) sendfile(client_fd, fd, 0, atoi(cl_str)); - - free(target); - free(cl_str); } - // Log response - method = get_http_method(req->method); - target = string_to_charptr(req->target); - print_log_response(resp->status_code, method, target, client_ip); - free(method); - free(target); - // Free string_destroy(str); string_destroy(res); @@ -331,19 +248,7 @@ struct http_request *parse_request(struct string *req) size_t i = 0; ssize_t nread = parse_reqline(res, req); if (nread <= 0) - { - if (nread == ERR_HTTP_NOT_IMPLEMENTED) - res->status_code = 501; - else - res->status_code = 400; - - if (res->target == NULL) - res->target = string_create("", 0); - if (res->protocol == NULL) - res->protocol = string_create("HTTP/1.1", 8); - - return res; - } + return NULL; // Split path and query split_target(res); @@ -353,10 +258,7 @@ struct http_request *parse_request(struct string *req) // Headers nread = parse_headers(res, req, i); if (nread <= 0) - { - res->status_code = 400; - return res; - } + return NULL; return res; } @@ -370,69 +272,35 @@ struct http_response *generate_response(struct http_request *req) return NULL; // Protocol - // char *protocol = HTTP_VERSION; - char *protocol = "HTTP/1.1"; + char *protocol = HTTP_VERSION; res->protocol = string_create(protocol, strlen(protocol)); - // Target - if (req->status_code == 0) - { - str_concat_string(config->servers->root_dir, - strlen(config->servers->root_dir), req->target); - } - // Status code if (req->status_code == 0) { - switch (find_target(req)) - { - case FILES_REG: - res->status_code = 200; - break; - case ERR_FILES_NOT_FOUND: + if (!find_target(req)) res->status_code = 404; - break; - default: - res->status_code = 403; - break; - } + else + res->status_code = 200; } - else - res->status_code = req->status_code; - // Check protocol and method - if (req->status_code == 0) - check_req(req, res); + // Status msg + res->status_msg = generate_status_message(res->status_code); // Headers char *time = get_time(); append_header(&res->headers, create_header("Date", time)); - free(time); // Yes, the one that completely disapeared this year + // free(time); // Yes, the one that completely disapeared this year + // Oopa if (res->status_code == 200) { - char buf[21] = { 0 }; // (20 ~= log10(2^64)) + 1 (null byte) + char buf[21] = { 0 }; // (21 ~= log10(2^64)) + 1 (null byte) char *target = string_to_charptr(req->target); - ssize_t cl = get_file_content_size(target); - free(target); - if (cl >= 0) - { - sprintf(buf, "%lu", cl); - append_header(&res->headers, create_header("Content-Length", buf)); - } - else - { - res->status_code = 403; - } - } - else - { - append_header(&res->headers, create_header("Content-Length", "0")); + sprintf(buf, "%lu", get_file_content_size(target)); + append_header(&res->headers, create_header("Content-Length", buf)); } append_header(&res->headers, create_header("Connection", "close")); - // Status msg - res->status_msg = generate_status_message(res->status_code); - return res; } @@ -458,6 +326,10 @@ struct string *format_response(struct http_response *resp) string_concat_str(res, "\r\n", 2); + // Time + char *time = get_time(); + string_concat_str(res, time, strlen(time)); + // Headers struct http_header *cur_header = resp->headers; while (cur_header != NULL) @@ -465,11 +337,6 @@ struct string *format_response(struct http_response *resp) string_concat_str(res, cur_header->field->data, cur_header->field->size); - string_concat_str(res, ": ", 2); - - string_concat_str(res, cur_header->value->data, - cur_header->value->size); - string_concat_str(res, "\r\n", 2); cur_header = cur_header->next; diff --git a/src/http/http.h b/httpd/src/http/http.h similarity index 86% rename from src/http/http.h rename to httpd/src/http/http.h index 8c3565c..0a895da 100644 --- a/src/http/http.h +++ b/httpd/src/http/http.h @@ -13,14 +13,13 @@ // === Includes -#include "../config/config.h" #include "../utils/string/string.h" +#include "../config/config.h" // === Enums enum http_method { - INVALID_METHOD, GET, // POST, // PUT, @@ -43,7 +42,7 @@ struct http_header struct http_request { - enum http_method method; + enum http_method method; struct string *target; struct string *queries; struct string *protocol; @@ -67,13 +66,13 @@ struct http_response * * @param cfg */ -void http_init(struct config *cfg); + void http_init(struct config* cfg); /* @brief Reads, parses the request and responds adequately all-in-one * * @param client_fd */ -void handle_request(int client_fd, char *client_ip); + void handle_request(int client_fd); /* @brief Parses the HTTP request and splits it into a request structure * @@ -82,7 +81,7 @@ void handle_request(int client_fd, char *client_ip); * @return A pointer to the structure containing the request infos on success, * NULL otherwise */ -struct http_request *parse_request(struct string *req); + struct http_request* parse_request(struct string* req); /* @brief Generates a response to the given request * @@ -91,7 +90,7 @@ struct http_request *parse_request(struct string *req); * @return A pointer to the generated response struct on success, * NULL otherwise */ -struct http_response *generate_response(struct http_request *req); + struct http_response* generate_response(struct http_request* req); /* @brief Formats the given response structure into a valid HTTP response * string @@ -101,7 +100,7 @@ struct http_response *generate_response(struct http_request *req); * @return A pointer to the string containing the response on success, * NULL otherwise */ -struct string *format_response(struct http_response *resp); + struct string* format_response(struct http_response* resp); /* @brief Free all allocated memory inside req and req itself * diff --git a/src/logger/errors.c b/httpd/src/logger/errors.c similarity index 68% rename from src/logger/errors.c rename to httpd/src/logger/errors.c index 4bbb369..c5f2c6e 100644 --- a/src/logger/errors.c +++ b/httpd/src/logger/errors.c @@ -4,9 +4,7 @@ #include #include -#include #include -#include #include "../utils/time/fmt_time.h" #include "logs.h" @@ -17,16 +15,13 @@ static struct logs_config config; // === Functions -void errlog_init(bool enabled, int logfile_fd, struct server_config *serv_cfg) +void errlog_init(bool enabled, int logfile_fd) { config.enabled = enabled; - if (logfile_fd == STDOUT_FILENO) - config.logfile_fd = STDERR_FILENO; config.logfile_fd = logfile_fd; - config.server_cfg = serv_cfg; } -void print_err(void) +void print_err() { print_log_err("%s", get_err()); } @@ -37,10 +32,8 @@ void print_log_err(char *format, ...) return; // Log prefix (time and server name) - char *time = get_time(); - dprintf(config.logfile_fd, "%s [%s] ERROR ", time, + dprintf(config.logfile_fd, "%s [%s] ", get_time(), config.server_cfg->server_name); - free(time); // Print actual log va_list args; @@ -55,7 +48,7 @@ void print_log_err(char *format, ...) fprintf(stderr, "Error: %s", get_err()); } -char *get_err(void) +char *get_err() { return strerror(errno); } diff --git a/src/logger/errors.h b/httpd/src/logger/errors.h similarity index 50% rename from src/logger/errors.h rename to httpd/src/logger/errors.h index 09b8be2..2d9303c 100644 --- a/src/logger/errors.h +++ b/httpd/src/logger/errors.h @@ -4,24 +4,22 @@ #include #include -#include "../config/config.h" - /* @brief Initialize the error logging submodule * @warning Do not use 'as is', use log_init() instead */ -void errlog_init(bool enabled, int logfile_fd, struct server_config *serv_cfg); +void errlog_init(bool enabled, int logfile_fd); /* @brief Retrieves the last error with errno and prints the corresponding * error message in the logs and stderr */ -void print_err(void); +void print_err(); -/* @brief Prints error logs, just like print_log() but for errors +/* @brief Prints error logs, just like print_log(), and also to stderr */ -void print_log_err(char *format, ...); +void print_log_err(char* format, ...); -/* @brief Returns the string corresponding to the last error that happened +/* @brief Prints error logs, just like print_log() */ -char *get_err(void); +char* get_err(); #endif // ! ERRORS_H diff --git a/httpd/src/logger/logs.c b/httpd/src/logger/logs.c new file mode 100644 index 0000000..2f98923 --- /dev/null +++ b/httpd/src/logger/logs.c @@ -0,0 +1,63 @@ +#define _POSIX_C_SOURCE 200809L + +#include "logs.h" + +#include +#include + +#include "../utils/time/fmt_time.h" +#include "errors.h" + +// === Static variables + +static struct logs_config config; + +// === Functions + +int log_init(struct config *global_config) +{ + int return_value = 0; + config.enabled = global_config->log; + config.server_cfg = global_config->servers; + config.logfile_fd = open(global_config->log_file, O_WRONLY); + if (config.logfile_fd <= 0) + { + config.enabled = false; + return_value = 1; + } + errlog_init(config.enabled, config.logfile_fd); + return return_value; +} + +void print_log(char *format, ...) +{ + if (!config.enabled) + return; + + // Log prefix (time and server name) + dprintf(config.logfile_fd, "%s [%s] ", get_time(), + config.server_cfg->server_name); + + // Print actual log + va_list args; + va_start(args, format); + vdprintf(config.logfile_fd, format, args); + va_end(args); + + // New line + dprintf(config.logfile_fd, "\n"); +} + +void log_request(char *request_type, char *target, char *client_ip) +{ + print_log("received %s, on '%s' from %s", get_time(), + config.server_cfg->server_name, request_type, target, client_ip); +} + +void log_response(int status_code, char *request_type, char *target, + char *client_ip) +{ + print_log("responding with %d to %s for %s on '%s'", get_time(), + config.server_cfg->server_name, status_code, client_ip, + request_type, target); +} diff --git a/src/logger/logs.h b/httpd/src/logger/logs.h similarity index 68% rename from src/logger/logs.h rename to httpd/src/logger/logs.h index f18a6d4..e8f337d 100644 --- a/src/logger/logs.h +++ b/httpd/src/logger/logs.h @@ -9,7 +9,7 @@ struct logs_config { bool enabled; int logfile_fd; - struct server_config *server_cfg; + struct server_config* server_cfg; }; /* @brief Initializes the logging module @@ -18,7 +18,7 @@ struct logs_config * * @return 0 on success, an error code otherwise */ -int log_init(struct config *config); +int log_init(struct config* config); /* @brief Prints logs (or not) conformly to the config given by the user. * Works like printf (because it uses it under the hood) with a @@ -27,7 +27,7 @@ int log_init(struct config *config); * @param format * @param ... */ -void print_log(char *format, ...); +void print_log(char* format, ...); /* @brief Prints request logs with the adequate format in the logfile * @@ -35,7 +35,7 @@ void print_log(char *format, ...); * @param target * @param client_ip */ -void print_log_request(char *request_type, char *target, char *client_ip); +void log_request(char* request_type, char* target, char* client_ip); /* @brief Prints response logs with the adequate format in the logfile * @@ -44,11 +44,8 @@ void print_log_request(char *request_type, char *target, char *client_ip); * @param target * @param client_ip */ -void print_log_response(int status_code, char *request_type, char *target, - char *client_ip); +void log_response(int status_code, char* request_type, char* target, char* client_ip); + -/* @brief Gracefully exits the logs module - */ -void log_terminate(void); #endif // ! LOGS_H diff --git a/src/main.c b/httpd/src/main.c similarity index 89% rename from src/main.c rename to httpd/src/main.c index 6f2c5b2..8e36192 100644 --- a/src/main.c +++ b/httpd/src/main.c @@ -18,13 +18,12 @@ int main(int argc, char **argv) // Initialize modules log_init(config); // Ignore ret val http_init(config); - daemon_init(config); // Start server switch (config->daemon) { case NO_OPTION: - start_server(config); + start_server("localhost", config->servers->port); break; case START: @@ -43,6 +42,5 @@ int main(int argc, char **argv) return 2; } - config_destroy(config); return 0; } diff --git a/src/server/server.c b/httpd/src/server/server.c similarity index 61% rename from src/server/server.c rename to httpd/src/server/server.c index 56c0c53..850754b 100644 --- a/src/server/server.c +++ b/httpd/src/server/server.c @@ -7,25 +7,16 @@ // === Includes #include "server.h" -#include #include -#include #include #include -#include #include #include #include "../http/http.h" #include "../logger/errors.h" -#include "../logger/logs.h" // #include "../logger/logs.h" -// === Static variables - -static int server_socket = 0; -static struct config *config; - // === Static functions // Creates and bind the server communication socket @@ -101,40 +92,11 @@ static int get_socket(const char *hostname, const char *port) // } // } -// Retrieves client ipv4 address and stores it in res -// WARNING: res must be of size INET_ADDRSTRLEN -static void get_ip(struct sockaddr *client_addr, char *res) -{ - // NOTE: exceptionally authorized cast - struct in_addr ipAddr = ((struct sockaddr_in *)client_addr)->sin_addr; - inet_ntop(AF_INET, &ipAddr, res, INET_ADDRSTRLEN); -} - -static void signal_handler(int signal) -{ - print_log("EVENT Signal received: %d", signal); - switch (signal) - { - case SIGINT: { - print_log("STOPPING Stopping server..."); - stop_server(); - config_destroy(config); - exit(0); - } - default: - return; - } -} - // === Functions -void start_server(struct config *cfg) +void start_server(const char *host, const char *port) { - config = cfg; - const char *host = config->servers->ip; - const char *port = config->servers->port; - - server_socket = get_socket(host, port); + int server_socket = get_socket(host, port); if (server_socket == -1) // TODO log that return; @@ -143,42 +105,19 @@ void start_server(struct config *cfg) if (err == -1) return; - // Signal handling - struct sigaction siga; - siga.sa_flags = 0; - siga.sa_handler = signal_handler; - // initialize mask - if (sigemptyset(&siga.sa_mask) < 0) - // TODO log that - return; - if (sigaction(SIGINT, &siga, NULL) == -1 - || sigaction(SIGPIPE, &siga, NULL) == -1) - return; - // Main loop while (1) { - struct sockaddr client_addr; - socklen_t client_addr_len = sizeof(struct sockaddr); - int client_fd = accept(server_socket, &client_addr, &client_addr_len); + int client_fd = accept(server_socket, NULL, NULL); if (client_fd == -1) continue; // TODO handle signals to stop - // Get ip - char client_ip[INET_ADDRSTRLEN]; - get_ip(&client_addr, client_ip); - - handle_request(client_fd, client_ip); + handle_request(client_fd); // send_back(client_fd); close(client_fd); } - stop_server(); -} - -void stop_server(void) -{ close(server_socket); } diff --git a/httpd/src/server/server.h b/httpd/src/server/server.h new file mode 100644 index 0000000..407ec1a --- /dev/null +++ b/httpd/src/server/server.h @@ -0,0 +1,13 @@ +#ifndef SERVER_H +#define SERVER_H + +// #define _POSIX_C_SOURCE 200112L + +/* @brief + * + * @param hpstname + * @param port + */ +void start_server(const char* host, const char* port); + +#endif // ! SERVER_H diff --git a/httpd/src/utils/files/files.c b/httpd/src/utils/files/files.c new file mode 100644 index 0000000..a4a30ee --- /dev/null +++ b/httpd/src/utils/files/files.c @@ -0,0 +1,61 @@ +#include "files.h" + +#include +// #include +#include + +// #include "../string/string.h" + +// bool file_exists(const char *path) +// {} + +int is_directory(const char *path) +{ + struct stat path_stat; + if (stat(path, &path_stat) != 0) + return S_ISDIR(path_stat.st_mode); + else + return -1; +} + +// TODO handle logging +// struct string *get_file_content(const char *path) +// { +// // Open file +// FILE *stream = fopen(path, "r"); +// if (stream == NULL) +// return NULL; + +// // Alloc result +// char buf[BUFFER_SIZE]; +// struct string *res = string_create(NULL, 0); +// if (res == NULL) +// { +// return NULL; +// } + +// int nread; +// while ((fgets(buf, BUFFER_SIZE, stream))) +// } + +// TODO not implemented +bool check_filename(struct string *path) +{ + if (path == NULL || path->size <= 0) + return false; + + return true; +} + +ssize_t get_file_content_size(const char *path) +{ + FILE *stream = fopen(path, "r"); + if (stream == NULL) + return -2; + + fseek(stream, 0, SEEK_END); + ssize_t res = ftell(stream); + fclose(stream); + + return res; +} diff --git a/httpd/src/utils/files/files.h b/httpd/src/utils/files/files.h new file mode 100644 index 0000000..2afc287 --- /dev/null +++ b/httpd/src/utils/files/files.h @@ -0,0 +1,82 @@ +#ifndef FILES_H +#define FILES_H + +// === Definitions + +#define BUFFER_SIZE 1024 + +// === Includes + +#include +#include +#include + +#include "../string/string.h" + +// === Functions + +/* + * @brief + * + * @param path + * + * @return + */ +// bool file_exists(const char *path); + +/* + * @brief + * + * @param path + * + * @return 1 if path is a directory, 0 if it is not and -1 if path is not valid + */ +int is_directory(const char* path); + +/* + * @brief + * + * @param path + * + * @return + */ + char* get_file(const char* path); + + +/* + * @brief + * + * @param path + * + * @return + */ +struct string* get_file_content(const char *path); + +/* + * @brief + * + * @param path + * + * @return + */ +bool check_filename(struct string* path); + +/* + * @brief + * + * @param filename + * + * @return + */ +bool sanitize_filename(struct string* filename); + +/* + * @brief + * + * @param path + * + * @return + */ + ssize_t get_file_content_size(const char* path); + +#endif // ! FILES_H diff --git a/src/utils/parsing/blanks.c b/httpd/src/utils/parsing/blanks.c similarity index 100% rename from src/utils/parsing/blanks.c rename to httpd/src/utils/parsing/blanks.c diff --git a/src/utils/parsing/blanks.h b/httpd/src/utils/parsing/blanks.h similarity index 91% rename from src/utils/parsing/blanks.h rename to httpd/src/utils/parsing/blanks.h index 417dc0a..68c9778 100644 --- a/src/utils/parsing/blanks.h +++ b/httpd/src/utils/parsing/blanks.h @@ -8,9 +8,8 @@ // === Includes #include -#include #include - +#include #include "../string/string.h" // === Functions @@ -34,6 +33,6 @@ bool is_blank(char c); /* * Doc: TODO */ -ssize_t skip_blanks(struct string *str, size_t offset); +ssize_t skip_blanks(struct string* str, size_t offset); #endif // ! BLANKS_H diff --git a/src/utils/parsing/words.c b/httpd/src/utils/parsing/words.c similarity index 100% rename from src/utils/parsing/words.c rename to httpd/src/utils/parsing/words.c diff --git a/src/utils/parsing/words.h b/httpd/src/utils/parsing/words.h similarity index 74% rename from src/utils/parsing/words.h rename to httpd/src/utils/parsing/words.h index d259bff..265212b 100644 --- a/src/utils/parsing/words.h +++ b/httpd/src/utils/parsing/words.h @@ -1,12 +1,12 @@ #ifndef WORDS_H #define WORDS_H + // === Includes -#include #include +#include #include - #include "../string/string.h" // === Functions @@ -19,7 +19,7 @@ bool str_contains(const char *str, char c); /* * Doc: TODO */ -ssize_t read_word(struct string *str, size_t offset, struct string **res); +ssize_t read_word(struct string* str, size_t offset, struct string** res); /* * Doc: TODO @@ -30,8 +30,8 @@ ssize_t read_word_delim(struct string *str, size_t offset, struct string **res, /* * Doc: TODO */ -ssize_t read_word_restrict(struct string *str, size_t offset, - struct string **res, const char *restr); +ssize_t read_word_restrict(struct string *str, size_t offset, struct string **res, + const char *restr); /* * Doc: TODO diff --git a/src/utils/string/string.c b/httpd/src/utils/string/string.c similarity index 59% rename from src/utils/string/string.c rename to httpd/src/utils/string/string.c index 5a28b5a..78b3879 100644 --- a/src/utils/string/string.c +++ b/httpd/src/utils/string/string.c @@ -67,7 +67,7 @@ void string_concat_str(struct string *str, const char *to_concat, size_t size) } else { - str->data = realloc(str->data, new_size * sizeof(char)); + str->data = realloc(str->data, new_size); if (str->data == NULL) return; // Handle ? } @@ -78,46 +78,6 @@ void string_concat_str(struct string *str, const char *to_concat, size_t size) } } -void str_concat_string(const char *str, size_t size, struct string *to_concat) -{ - size_t new_size = to_concat->size + size; - size_t tmp_size = to_concat->size; - - if (new_size == 0) - return; - - to_concat->size = new_size; - if (tmp_size == 0) - { - to_concat->data = malloc(new_size); - if (to_concat->data == NULL) - return; // Handle ? - } - else - { - // Temporary buffer - char *tmp = malloc(tmp_size * sizeof(char)); - if (tmp == NULL) - return; // Handle ? - - // (Duplicate) - memcpy(tmp, to_concat->data, tmp_size); - - // Reallocate string - char *new_data = realloc(to_concat->data, new_size * sizeof(char)); - if (to_concat->data == NULL) - { - to_concat->size = tmp_size; // Restore (original ptr still valid) - return; // Handle ? - } - to_concat->data = new_data; - - memcpy(to_concat->data, str, size); - memcpy(to_concat->data + size, tmp, tmp_size); - free(tmp); - } -} - void string_to_lowercase(struct string *str) { for (size_t i = 0; i < str->size; i++) @@ -154,22 +114,3 @@ char *string_to_charptr(struct string *str) return res; } - -// WARNING takes n as valid, will not stop on '\0' -int string_compare_strictly_n_str(const struct string *str1, const char *str2, - size_t n) -{ - if (str1->size < n) - return -1; - - size_t i = 0; - int res = 0; - while (i < n) - { - res += str1->data[i]; - res -= str2[i]; - i++; - } - - return res; -} diff --git a/src/utils/string/string.h b/httpd/src/utils/string/string.h similarity index 72% rename from src/utils/string/string.h rename to httpd/src/utils/string/string.h index a69f47c..62bca63 100644 --- a/src/utils/string/string.h +++ b/httpd/src/utils/string/string.h @@ -42,16 +42,6 @@ int string_compare_n_str(const struct string *str1, const char *str2, size_t n); */ void string_concat_str(struct string *str, const char *to_concat, size_t size); -/* - ** @brief Similar to string_concat_str but with str at the beginning of the - * result string - ** - ** @param str - ** @param to_concat - ** @param size - */ -void str_concat_string(const char *str, size_t size, struct string *to_concat); - /* ** @brief Concat a char * with its size in a struct string ** @@ -73,17 +63,6 @@ void string_destroy(struct string *str); ** ** @return a pointer to an allocated memory zone containing the string */ -char *string_to_charptr(struct string *str); +char* string_to_charptr(struct string *str); -/* - ** @brief TODO - ** - ** @param str1 - ** @param str2 - ** @param n - ** - ** @return - */ -int string_compare_strictly_n_str(const struct string *str1, const char *str2, - size_t n); #endif /* ! STRING_H */ diff --git a/httpd/src/utils/time/fmt_time.c b/httpd/src/utils/time/fmt_time.c new file mode 100644 index 0000000..a2590e4 --- /dev/null +++ b/httpd/src/utils/time/fmt_time.c @@ -0,0 +1,10 @@ +#include "fmt_time.h" + +#include + +char *get_time(void) +{ + time_t local_ts = time(NULL); + struct tm *gmt_time = gmtime(&local_ts); + return asctime(gmt_time); +} diff --git a/src/utils/time/fmt_time.h b/httpd/src/utils/time/fmt_time.h similarity index 93% rename from src/utils/time/fmt_time.h rename to httpd/src/utils/time/fmt_time.h index 81d5bd8..43f7877 100644 --- a/src/utils/time/fmt_time.h +++ b/httpd/src/utils/time/fmt_time.h @@ -6,6 +6,6 @@ * * @return A NULL-terminated string containing the fromatted GMT time */ -char *get_time(); +char* get_time(); #endif // ! FMT_TIME_H diff --git a/src/logger/logs.c b/src/logger/logs.c deleted file mode 100644 index f82f706..0000000 --- a/src/logger/logs.c +++ /dev/null @@ -1,79 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include "logs.h" - -#include -#include -#include -#include - -#include "../utils/time/fmt_time.h" -#include "errors.h" - -// === Static variables - -static struct logs_config config; - -// === Functions - -int log_init(struct config *global_config) -{ - int return_value = 0; - config.enabled = global_config->log; - config.server_cfg = global_config->servers; - if (global_config->log_file != NULL) - { - config.logfile_fd = open(global_config->log_file, O_WRONLY); - if (config.logfile_fd <= 0) - { - config.enabled = false; - return_value = 1; - } - } - else - { - config.logfile_fd = STDOUT_FILENO; - } - - errlog_init(config.enabled, config.logfile_fd, config.server_cfg); - return return_value; -} - -void print_log(char *format, ...) -{ - if (!config.enabled) - return; - - // Log prefix (time and server name) - char *time = get_time(); - dprintf(config.logfile_fd, "%s [%s] ", time, - config.server_cfg->server_name); - free(time); - - // Print actual log - va_list args; - va_start(args, format); - vdprintf(config.logfile_fd, format, args); - va_end(args); - - // New line - dprintf(config.logfile_fd, "\n"); -} - -void print_log_request(char *request_type, char *target, char *client_ip) -{ - print_log("received %s, on '%s' from %s", request_type, target, client_ip); -} - -void print_log_response(int status_code, char *request_type, char *target, - char *client_ip) -{ - print_log("responding with %d to %s for %s on '%s'", status_code, client_ip, - request_type, target); -} - -void log_terminate(void) -{ - if (config.logfile_fd != 0 && config.logfile_fd != STDOUT_FILENO) - close(config.logfile_fd); -} diff --git a/src/server/server.h b/src/server/server.h deleted file mode 100644 index 0c441ac..0000000 --- a/src/server/server.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SERVER_H -#define SERVER_H - -#include "../config/config.h" - -/* @brief Starts the HTTP server - * - * @warn Make sure to initialize modules before calling - * - * @param hostname - * @param port - */ -void start_server(struct config *cfg); - -/* @brief Stops the currently running HTTP server - */ -void stop_server(void); - -#endif // ! SERVER_H diff --git a/src/utils/files/files.c b/src/utils/files/files.c deleted file mode 100644 index 0f08c25..0000000 --- a/src/utils/files/files.c +++ /dev/null @@ -1,105 +0,0 @@ -#define _POSIX_C_SOURCE 200112L - -#include "files.h" - -#include -#include -#include - -// #include "../string/string.h" - -// int file_exists(const char *path) -// {} - -int is_directory(const char *path) -{ - struct stat path_stat; - if (lstat(path, &path_stat) == 0) - { - if (S_ISDIR(path_stat.st_mode)) // Directory - return FILES_DIR; - else if (S_ISREG(path_stat.st_mode)) // Regular file - return FILES_REG; - else - return FILES_OTHER; - } - else - { - if (errno == ENOENT) // File not found - return ERR_FILES_NOT_FOUND; - else // Other errors - return ERR_FILES_FORBIDDEN; - } -} - -// TODO handle logging -// struct string *get_file_content(const char *path) -// { -// // Open file -// FILE *stream = fopen(path, "r"); -// if (stream == NULL) -// return NULL; - -// // Alloc result -// char buf[BUFFER_SIZE]; -// struct string *res = string_create(NULL, 0); -// if (res == NULL) -// { -// return NULL; -// } - -// int nread; -// while ((fgets(buf, BUFFER_SIZE, stream))) -// } - -// TODO not implemented -bool check_filename(struct string *path) -{ - if (path == NULL || path->size <= 0) - return false; - - return true; -} - -ssize_t get_file_content_size(const char *path) -{ - FILE *stream = fopen(path, "r"); - if (stream == NULL) - return -2; - - fseek(stream, 0, SEEK_END); - ssize_t res = ftell(stream); - fclose(stream); - - return res; -} - -int write_to_file(const char *path, struct string *buf) -{ - FILE *stream = fopen(path, "w"); - if (stream == NULL) - return 1; - - fwrite(buf->data, sizeof(char), buf->size, stream); - - fclose(stream); - - return 0; -} - -int write_pid(const char *filepath, int pid) -{ - FILE *stream = fopen(filepath, "w"); - if (stream == NULL) - return 1; - - if (fprintf(stream, "%d", pid) <= 0) - { - fclose(stream); - return 1; - } - - fclose(stream); - - return 0; -} diff --git a/src/utils/files/files.h b/src/utils/files/files.h deleted file mode 100644 index 0c2cdcc..0000000 --- a/src/utils/files/files.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef FILES_H -#define FILES_H - -// === Definitions - -#define BUFFER_SIZE 1024 - -// Return codes -#define FILES_REG 0 -#define FILES_DIR 1 -#define FILES_OTHER 8 - -// Errors -#define ERR_FILES_NOT_FOUND -1 -#define ERR_FILES_FORBIDDEN -2 - -// === Includes - -#include -#include -#include - -#include "../string/string.h" - -// === Functions - -/* - * @brief - * - * @param path - * - * @return - */ -// bool file_exists(const char *path); - -/* - * @brief - * - * @param path - * - * @return Returns the corresponding return value / error code (see header - * definitions) - */ -int is_directory(const char *path); - -/* - * @brief - * - * @param path - * - * @return - */ -// char *get_file(const char *path); - -/* - * @brief - * - * @param path - * - * @return - */ -struct string *get_file_content(const char *path); - -/* - * @brief - * - * @param path - * - * @return - */ -bool check_filename(struct string *path); - -/* - * @brief - * - * @param filename - * - * @return - */ -// bool sanitize_filename(struct string *filename); - -/* - * @brief - * - * @param path - * - * @return - */ -ssize_t get_file_content_size(const char *path); - -/* - * @brief - * - * @param path - * - * @return 0 on success, the corresponding error code otherwise - */ -int write_to_file(const char *path, struct string *buf); - -/* - * @brief - * - * @param path - * - * @return 0 on success, the corresponding error code otherwise - */ -int write_pid(const char *filepath, int pid); - -#endif // ! FILES_H diff --git a/src/utils/time/fmt_time.c b/src/utils/time/fmt_time.c deleted file mode 100644 index cc37959..0000000 --- a/src/utils/time/fmt_time.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "fmt_time.h" - -#include -#include - -char *get_time(void) -{ - char *buf = malloc(64 * sizeof(char)); // Oui, 64 - time_t local_ts = time(NULL); - struct tm *gmt_time = gmtime(&local_ts); - - // return asctime(gmt_time); - strftime(buf, 64, "%a, %d %b %Y %H:%M:%S %Z", gmt_time); - return buf; -} diff --git a/tests/test_root_dir/index.html b/tests/test_root_dir/index.html deleted file mode 100644 index f5bf13f..0000000 --- a/tests/test_root_dir/index.html +++ /dev/null @@ -1 +0,0 @@ -

YEAAH

diff --git a/tests/test_suite.py b/tests/test_suite.py deleted file mode 100644 index 504f05a..0000000 --- a/tests/test_suite.py +++ /dev/null @@ -1,178 +0,0 @@ -import subprocess as sp -import http -import requests -import socket -import pytest -import time - -host = "127.0.0.1" -port = "6994" - -executable = "./httpd" - -def spawn_httpd(stdout_filename, args=[]): - with open(stdout_filename,"w") as f: - httpd_proc = sp.Popen([executable,"--pid_file","/tmp/HTTPd.pid","--ip",host,"--port", port, "--root_dir","test_root_dir/","--server_name","httpd"] if args == [] else [executable] + args, stdout=f,stderr=sp.PIPE,bufsize=0) - time.sleep(0.2) - - return httpd_proc - -def kill_httpd(proc): - #proc.send_signal(sp.SIGINT) - proc.kill() - -# @pytest.mark.timeout(2) -def test_bad_config(): - proc = spawn_httpd("out.log", ["hello","world"]) - proc.wait(1) - try: - assert proc.returncode == 2 - finally: - kill_httpd(proc) - -# @pytest.mark.timeout(2) -def test_get_index(): - proc = spawn_httpd("out.log") - req = requests.get(f"http://{host}:{port}/index.html") - assert req.status_code == 200 - with open("./test_root_dir/index.html","r") as f: - try: - assert f.read() == req.text - finally: - kill_httpd(proc) - -# @pytest.mark.timeout(2) -def test_get_default(): - proc = spawn_httpd("out.log") - req = requests.get(f"http://{host}:{port}/") - assert req.status_code == 200 - with open("./test_root_dir/index.html","r") as f: - try: - assert f.read() == req.text - finally: - kill_httpd(proc) - -# @pytest.mark.timeout(2) -def test_no_file(): - proc = spawn_httpd("out.log") - req = requests.get(f"http://{host}:{port}/notindex.html") - assert req.status_code == 404 - -# @pytest.mark.timeout(2) -def test_bad_request(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"GET /index.html FTP/1.1\r\nHOST: {host}:{port}\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - resp = sock.recv(1024) - resp_decoded = resp.decode() - - try: - assert "400 Bad Request" in resp_decoded - finally: - kill_httpd(proc) - -# @pytest.mark.timeout(2) -def test_invalid_method(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"PUT /index.html HTTP/1.1\r\nHOST: {host}:{port}\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - response = http.client.HTTPResponse(sock) - response.begin() - - try: - assert response.status == 405 - finally: - kill_httpd(proc) - - -# @pytest.mark.timeout(2) -def test_invalid_version(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"GET /index.html HTTP/1.2\r\nHOST: {host}:{port}\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - response = http.client.HTTPResponse(sock) - response.begin() - - try: - assert response.status == 505 - finally: - kill_httpd(proc) - -# @pytest.mark.timeout(2) -def test_bad_request(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"GET /index.html FTP/1.1\r\nHOST: {host}:{port}\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - response = http.client.HTTPResponse(sock) - response.begin() - - try: - assert response.status == 400 - finally: - kill_httpd(proc) - -@pytest.mark.timeout(2) -def test_head_index(): - proc = spawn_httpd("out.log") - try: - req = requests.head(f"http://{host}:{port}/index.html") - assert req.status_code == 200 - assert req.text == "" - finally: - kill_httpd(proc) - -@pytest.mark.timeout(2) -def test_missing_host(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"GET /index.html HTTP/1.1\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - response = http.client.HTTPResponse(sock) - response.begin() - - try: - assert response.status == 400 - finally: - kill_httpd(proc) - -@pytest.mark.timeout(2) -def test_directory_traversal(): - proc = spawn_httpd("out.log") - sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) - sock.connect((host,int(port))) - - request = f"GET /../test_suite.py HTTP/1.1\r\nHOST: {host}:{port}\r\nConnection: close\r\n\r\n" - - sock.sendall(request.encode()) - - response = http.client.HTTPResponse(sock) - response.begin() - - try: - assert response.status in [400, 403, 404] - finally: - kill_httpd(proc) diff --git a/tests/tests_mieux.sh b/tests/tests_mieux.sh deleted file mode 100755 index 6851190..0000000 --- a/tests/tests_mieux.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -# Simple test script for HTTP/1.1 Host header compliance -# Usage: ./test_host_compliance.sh [IP] [PORT] - -IP=${1:-"127.0.0.1"} -PORT=${2:-"6996"} - -echo "Targeting server at $IP:$PORT" - -test_req() { - NAME="$1" - PAYLOAD="$2" - EXPECTED="$3" - - echo -n "Test: $NAME ... " - # Send payload, wait max 1s for response - RESP=$(printf "$PAYLOAD" | nc -w 1 $IP $PORT 2>/dev/null | head -n 1) - - if echo "$RESP" | grep -q "$EXPECTED"; then - echo "PASS" - else - echo "FAIL (Expected '$EXPECTED', got '$RESP')" - fi -} - -# 1. Valid Request -test_req "Valid Request" "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n" "200 OK" - -# 2. Missing Host Header -test_req "Missing Host" "GET / HTTP/1.1\r\n\r\n" "400 Bad Request" - -# 3. Empty Host Header -test_req "Empty Host" "GET / HTTP/1.1\r\nHost:\r\n\r\n" "400 Bad Request" - -# 4. Multiple Host Headers -test_req "Multiple Hosts" "GET / HTTP/1.1\r\nHost: a\r\nHost: b\r\n\r\n" "400 Bad Request" - -# 5. Bad Protocol Version (Should be 505 now with the fix) -test_req "Bad Protocol (HTTP/1.0)" "GET / HTTP/1.0\r\nHost: localhost\r\n\r\n" "505" \ No newline at end of file