http_request.h 2.78 KB
#ifndef __HTTP_REQUEST_H
#define __HTTP_REQUEST_H

#include "ll.h"

/**
 * Struct representing an HTTP request.
 * 
 * The `method`, `http_version`, and `path` fields are heap-allocated strings
 * that are owned by the struct and are freed by `request_free`.
 * 
 * The `headers` is a linked list dictionary of headers, also freed by
 * `request_free`.
 */
typedef struct {
    char *method;
    char *http_version;
    char *path;
    ll_map_t *headers;
} request_t;

/**
 * Initializes a new request struct with the given method, path, and HTTP version.
 * 
 * The `method`, `http_version`, and `path` strings are COPIED into the struct,
 * so the caller still owns the original strings and must free them once they
 * are no longer needed. I.e., they are all borrowed.
 * 
 * ```
 * // fine to use string literals, since they are copied
 * request_t *req = request_init("GET", "/index.html", "HTTP/1.1");
 * assert(strcmp(req->method, "GET") == 0);
 * assert(strcmp(req->path, "/index.html") == 0);
 * assert(strcmp(req->http_version, "HTTP/1.1") == 0);
 * request_free(req);
 * ```
 * ```
 * char *method = strdup("GET");
 * char *path = strdup("/index.html");
 * char *http_version = strdup("HTTP/1.1");
 * request_t *req = request_init(method, path, http_version);
 * assert(strcmp(req->method, "GET") == 0);
 * assert(strcmp(req->path, "/index.html") == 0);
 * assert(strcmp(req->http_version, "HTTP/1.1") == 0);
 * request_free(req);
 * // must also free the original strings
 * free(method);
 * free(path);
 * free(http_version);
 * 
 * The `headers` field is initialized as an empty linked list dictionary.
 */
request_t *request_init(const char *method, const char *path, const char *http_version);

/**
 * Frees the given request struct and all the strings inside it.
 * 
 * The `method`, `http_version`, and `path` strings are freed using free, and
 * the `headers` linked list dictionary is freed using `ll_free`.
 * 
 * ```
 * request_t *req = request_init("GET", "/index.html", "HTTP/1.1");
 * request_free(req);
 * ```
 */
void request_free(request_t *req);

/**
 * Parses an HTTP request from the given string contents, creating a new request
 * struct.
 * 
 * The function expects the contents to be a valid HTTP request with headers
 * separated by '\r\n'. The first line should contain the method, path, and
 * HTTP version separated by spaces. The headers should be key-value pairs
 * separated by a colon and a space.
 * 
 * It should be terminated by an additional '\r\n' after the headers.
 * 
 * The contents string is borrowed and not touched or modified by this function 
 * and so it freeing it, if necessary, is the callers responsibility.
 * 
 * The returned request should be freed using `request_free` when it is no
 * longer needed.
 */
request_t *request_parse(const char *contents);

#endif /* __HTTP_REQUEST_H */