From 6d5f3a5c34794d7f9f8c8729b2686e7246699a60 Mon Sep 17 00:00:00 2001 From: Nayan <33187059+GShadow5@users.noreply.github.com> Date: Wed, 7 May 2025 18:06:14 -0400 Subject: [PATCH] move http structs to new file and write struct handler functions --- http_stuff.c | 109 +++++++++++++++++++++++++++++++++++ http_stuff.h | 144 ++++++++++++++++++++++++++++++++++++++++++++++ request_handler.h | 17 ------ 3 files changed, 253 insertions(+), 17 deletions(-) create mode 100644 http_stuff.c create mode 100644 http_stuff.h diff --git a/http_stuff.c b/http_stuff.c new file mode 100644 index 0000000..acb153a --- /dev/null +++ b/http_stuff.c @@ -0,0 +1,109 @@ +#include "http_stuff.h" + +http_request* create_http_request() { + http_request* req = (http_request*)malloc(sizeof(http_request)); + req->method = NULL; + req->url = NULL; + req->num_headers = 0; + req->headers = NULL; + req->content_type = NULL; + req->content_length = 0; + req->body = NULL; + return req; +} + +http_response* create_http_response() { + http_response* res = (http_response*)malloc(sizeof(http_response)); + res->status_line = NULL; + res->num_headers = 0; + res->headers = NULL; + res->content_type = NULL; + res->content_length = 0; + res->body = NULL; + return res; +} + +http_request* free_http_request(http_request* req) { + free(req->method); + free(req->url); + free(req->headers); + free(req->content_type); + free(req->body); + free(req); + return NULL; +} + +http_response* free_http_response(http_response* res) { + free(res->status_line); + free(res->headers); + free(res->content_type); + free(res->body); + free(res); + return NULL; +} + +void print_http_request(http_request* req) { + printf("Method: %s\n", req->method); + printf("URL: %s\n", req->url); + printf("Headers:\n"); + for (int i = 0; i < req->num_headers; i++) { + printf("%s: %s\n", req->headers[i].key, req->headers[i].value); + } + printf("Content-Type: %s\n", req->content_type); + printf("Content-Length: %zu\n", req->content_length); + printf("Body:\n%s\n", req->body); +} + +void print_http_response(http_response* res) { + printf("Status Line: %s\n", res->status_line); + printf("Headers:\n"); + for (int i = 0; i < res->num_headers; i++) { + printf("%s: %s\n", res->headers[i].key, res->headers[i].value); + } + printf("Content-Type: %s\n", res->content_type); + printf("Content-Length: %zu\n", res->content_length); + printf("Body:\n%s\n", res->body); +} + +char* reponse_to_string(http_response* res) { + int total_length = 0; + int len_newline = strlen("\r\n"); + int len_crlf = strlen("\r\n\r\n"); + + 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_crlf; + total_length += strlen(res->body); + total_length += len_crlf; + total_length += 1; // For null terminator + + char* response = (char*)malloc(total_length); + strcpy(response, res->status_line); + 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\r\n"); + strcat(response, res->body); + strcat(response, "\r\n\r\n"); + return response; +} + +char* get_header_value_request(http_request* req, char* key) { + for (int i = 0; i < req->num_headers; i++) { + if (strcmp(req->headers[i].key, key) == 0) { + return req->headers[i].value; + } + } + return NULL; +} \ No newline at end of file diff --git a/http_stuff.h b/http_stuff.h new file mode 100644 index 0000000..1d1e56f --- /dev/null +++ b/http_stuff.h @@ -0,0 +1,144 @@ +#ifndef HTTP_STUFF_H +#define HTTP_STUFF_H + +#include +#include +#include + +/** + * Stores a key-value pair for http headers + */ +struct header_kv { + char* key; + char* value; +}; + +/** + * Stores an HTTP request + */ +struct http_request { + char* method; + char* url; + int num_headers; + struct header_kv* headers; + char* content_type; + size_t content_length; + char* body; +}; + +/** + * Stores an HTTP response + */ +struct http_response { + char* status_line; + int num_headers; + struct header_kv* headers; + char* content_type; + size_t content_length; + char* body; +}; + +typedef struct header_kv header_kv; +typedef struct http_request http_request; +typedef struct http_response http_response; + +/** + * Creates a new http_request struct with all values set to NULL/0. + * + * @return A pointer to the newly allocated http_request struct. + * + * @details + * The caller is responsible for freeing the returned struct when it is no + * longer needed. + */ +http_request* create_http_request(); + +/** + * Allocates memory for a new http_response struct and sets all its fields to 0 + * or NULL. This function is used to create a new empty http_response which can + * then be populated with data. + * + * @return A pointer to the new http_response struct + * + * @details + * The caller is responsible for freeing the returned struct when it is no + * longer needed. + */ +http_response* create_http_response(); + +/** + * Frees the memory associated with an http_request struct. This function is + * meant to be used to free the memory associated with a request after it has + * been processed. It returns NULL so that the return value can be used to set + * the value of the pointer passed to it. I.e. + * + * http_request* req = create_http_request(); + * + * req = free_http_request(req); + * + * @param req The request to free + * + * @return NULL + */ +http_request* free_http_request(http_request* req); + +/** + * Frees the memory associated with an http_response struct. This function is + * meant to be used to free the memory associated with a response after it has + * been sent. It returns NULL so that the return value can be used to set the + * value of the pointer passed to it. I.e. + * + * http_response* res = create_http_response(); + * + * res = free_http_response(res); + * + * @param res The response to free + * + * @return NULL + * + * @details + * + */ +http_response* free_http_response(http_response* res); + +/** + * Prints a formatted version of an http_request struct to stdout. This function + * is meant to be used for debugging purposes. + * + * @param req The request to print + */ +void print_http_request(http_request* req); + +/** + * Prints a formatted version of an http_response struct to stdout. This + * function is meant to be used for debugging purposes. + * + * @param res The response to print + */ +void print_http_response(http_response* res); + +/** + * Converts an http_response struct to a string in the format of a HTTP + * response. 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* reponse_to_string(http_response* res); + +/** + * Finds the value associated with a given key in an http_request's headers. + * + * @param req The request to search + * @param key The key to search for + * + * @return The char* associated with the given key, or NULL if the key is not + * present in the request's headers + */ +char* get_header_value_request(http_request* req, char* key); + +#endif \ No newline at end of file diff --git a/request_handler.h b/request_handler.h index 346ed01..84b63ef 100644 --- a/request_handler.h +++ b/request_handler.h @@ -5,23 +5,6 @@ #include #include -struct http_request { - char* method; - char* url; - char** headers; - int num_headers; - char* body; - size_t body_length; -}; - -struct http_response { - char* status_line; - char** headers; - int num_headers; - char* body; - size_t body_length; -}; - typedef struct http_request http_request; typedef struct http_response http_response;