diff --git a/client_handler.c b/client_handler.c index 6b34768..956f2af 100644 --- a/client_handler.c +++ b/client_handler.c @@ -28,14 +28,16 @@ void* client_handler(void* args) { buffer[bytes_read] = '\0'; // Allocate space for response - char* response = NULL; - size_t response_length = BUFFER_SIZE; + http_response* response = create_http_response(); // Handle request - handle_request(buffer, bytes_read, &response, &response_length); + handle_request(buffer, bytes_read, response); // Send response - send(client, response, response_length, 0); + char* headers = response_headers_to_string(response); + send(client, headers, strlen(headers), 0); + send(client, response->body, response->content_length, 0); + send(client, "\r\n", 2, 0); free(response); return NULL; diff --git a/http_stuff.c b/http_stuff.c index 6d78318..81b8181 100644 --- a/http_stuff.c +++ b/http_stuff.c @@ -138,7 +138,7 @@ char* response_to_string(http_response* res) { total_length += strlen("Content-Length: "); total_length += strlen(content_lenth_str); total_length += len_crlf; - total_length += strlen(res->body); + total_length += res->content_length; total_length += len_crlf; total_length += 1; // For null terminator @@ -161,6 +161,48 @@ char* response_to_string(http_response* res) { return response; } +char* response_headers_to_string(http_response* res) { + // Define lengths + int total_length = 0; + int len_newline = strlen("\r\n"); + int len_crlf = strlen("\r\n\r\n"); + + char* content_lenth_str = (char*)malloc(10); + sprintf(content_lenth_str, "%zu", res->content_length); + + // Calculate total length + total_length += strlen(res->status_line); + total_length += len_newline; + for (int i = 0; i < res->num_headers; i++) { + total_length += strlen(res->headers[i].key); + total_length += strlen(": "); + total_length += strlen(res->headers[i].value); + total_length += len_newline; + } + total_length += strlen(res->content_type); + total_length += len_newline; + total_length += strlen("Content-Length: "); + total_length += strlen(content_lenth_str); + total_length += len_crlf; + total_length += 1; // For null terminator + + char* response = (char*)malloc(total_length); + strcpy(response, res->status_line); + strcat(response, "\r\n"); + for (int i = 0; i < res->num_headers; i++) { + strcat(response, res->headers[i].key); + strcat(response, ": "); + strcat(response, res->headers[i].value); + strcat(response, "\r\n"); + } + strcat(response, res->content_type); + strcat(response, "\r\n"); + strcat(response, "Content-Length: "); + strcat(response, content_lenth_str); + strcat(response, "\r\n\r\n"); + return response; +} + char* get_header_value_request(http_request* req, char* key) { // printf("Getting header value for key: %s\n", key); for (int i = 0; i < req->num_headers; i++) { diff --git a/http_stuff.h b/http_stuff.h index 600be75..5a81a73 100644 --- a/http_stuff.h +++ b/http_stuff.h @@ -139,6 +139,19 @@ void print_http_response(http_response* res); */ char* response_to_string(http_response* res); +/** + * Returns the string representation of an http_response struct WITHOUT the + * body. This function is meant to be used when sending a response over a + * socket. It allocates memory for the string and returns a pointer to it, so + * the caller is responsible for freeing the memory when it is no longer + * needed. + * + * @param res The response to convert to a string + * + * @return A pointer to the string representation of the response + */ +char* response_headers_to_string(http_response* res); + /** * Finds the value associated with a given key in an http_request's headers. * diff --git a/public/image.png b/public/image.png new file mode 100644 index 0000000..bff699a Binary files /dev/null and b/public/image.png differ diff --git a/request_handler.c b/request_handler.c index cee8107..8e4c313 100644 --- a/request_handler.c +++ b/request_handler.c @@ -3,41 +3,19 @@ void parse_http_request(char* request, int length, struct http_request* req); void debug_print_request(char* request); -void handle_request(char* request, int length, char** response, - size_t* response_length) { +void handle_request(char* request, int length, http_response* response) { // Terminate request with EOF so strtok stops at end of string request[length] = EOF; - // printf("Request ---------\n"); - // printf("%s\n---------\n", request); - - // debug_print_request(request); - - // printf("parsing request ---------\n"); // Parse request into struct http_request* req = create_http_request(); parse_http_request(request, length, req); - // print_http_request(req); - // printf("---------\n"); - // request_info_print(req); - // free_http_request(req); // Switch statement to handle different request types switch (req->method) { case GET: // Build response - http_response* res = create_http_response(); - response_handle_get(req, res); - // Convert response to string - char* response_string = response_to_string(res); - // Copy string to response - char* responsestr = (char*)malloc(strlen(response_string) + 1); - strcpy(responsestr, response_string); - *response = responsestr; - // Set response length - *response_length = strlen(response_string); - // Free response - free_http_response(res); + response_handle_get(req, response); break; case POST: diff --git a/request_handler.h b/request_handler.h index df9d2e1..d667602 100644 --- a/request_handler.h +++ b/request_handler.h @@ -8,7 +8,6 @@ #include "http_stuff.h" #include "response_builder.h" -void handle_request(char* request, int length, char** response, - size_t* response_length); +void handle_request(char* request, int length, http_response* response); #endif \ No newline at end of file diff --git a/response_builder.c b/response_builder.c index ce8f843..5b7ae30 100644 --- a/response_builder.c +++ b/response_builder.c @@ -8,42 +8,28 @@ void response_handle_get(http_request* req, http_response* res) { strcat(file_path, req->url); printf("%s\n", file_path); - serve_404(res); - return; - // Determine the file type char* ptr = file_path + strlen(file_path) - 1; - size_t etc_len = 0; while (*ptr != '.') { - etc_len++; ptr--; } - char* etc = (char*)malloc(etc_len + 1); - strncpy(etc, ptr, etc_len); - etc[etc_len] = '\0'; - printf("%s\n", etc); - if (strcmp(etc, ".html") == 0) { + if (strcmp(ptr, ".html") == 0) { response_build_static_file(file_path, HTML, OK, res); - } else if (strcmp(etc, ".jpg") == 0) { + } else if (strcmp(ptr, ".jpg") == 0) { serve_404(res); return; - } else if (strcmp(etc, ".png") == 0) { + } else if (strcmp(ptr, ".png") == 0) { + response_build_static_file(file_path, PNG, OK, res); + } else if (strcmp(ptr, ".css") == 0) { serve_404(res); return; - } else if (strcmp(etc, ".css") == 0) { - serve_404(res); - return; - } else if (strcmp(etc, ".js") == 0) { + } else if (strcmp(ptr, ".js") == 0) { serve_404(res); return; } else { serve_404(res); return; } - - // Serve 404 if file not found or file type not supported (html, jpg, png - // only) - // Serve the file } void response_build_static_file(char* file_path, content_type content_type, @@ -145,6 +131,15 @@ void response_build_static_file(char* file_path, content_type content_type, } // Set content type string res->content_type = content_type_str; + + // Add header for close connection + header_kv* close_connection = (header_kv*)malloc(sizeof(header_kv)); + close_connection->key = (char*)malloc(strlen("Connection") + 1); + close_connection->value = (char*)malloc(strlen("close") + 1); + strcpy(close_connection->key, "Connection"); + strcpy(close_connection->value, "close"); + res->headers = close_connection; + res->num_headers = 1; } void serve_404(http_response* res) {