commit 223a7eee1a93f61f1cd381cdc790faacfc6fd3be
parent eb01fd0234ade747eea2d425829d6fc66553f30c
Author: cebem1nt <mineewarik@gmail.com>
Date: Sun, 23 Nov 2025 22:44:57 -0300
Bugfixes, removed nomem function, now returning NULL
Diffstat:
| M | httpp.h | | | 139 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
| M | test.c | | | 14 | ++++++++++++++ |
2 files changed, 95 insertions(+), 58 deletions(-)
diff --git a/httpp.h b/httpp.h
@@ -9,16 +9,19 @@
#include <stdlib.h>
#include <string.h>
-#define _HTTPP_LINE_BUFSIZE 4096
-#define _HTTPP_INITIAL_HEADERS_ARR_CAP 20
+#define HTTPP_LINE_BUFSIZE 4096
+#define HTTPP_INITIAL_HEADERS_ARR_CAP 20
-#define _HTTPP_MAX_METHOD_LENGTH (10 + 1)
-#define _HTTPP_VERSION_BUFSIZE (10 + 1)
+#define HTTPP_MAX_METHOD_LENGTH (10 + 1)
+#define HTTPP_VERSION_BUFSIZE (10 + 1)
#define httpp_string_to_method(s) (strcmp(s, "GET") == 0 ? 0 : \
strcmp(s, "POST") == 0 ? 1 : \
strcmp(s, "DELETE") == 0 ? 2 : -1)
+#define HTTPP_ERRMEMRY 3
+#define HTTPP_ERRLOGIC 1
+
typedef enum {
GET,
POST,
@@ -49,45 +52,33 @@ http_req_t* httpp_req_new();
http_req_t* httpp_parse_request(char* raw);
int httpp_parse_header(http_headers_arr_t* hs, char* line);
-void httpp_headers_append(http_headers_arr_t* hs, http_header_t header);
+int httpp_headers_append(http_headers_arr_t* hs, http_header_t header);
+void http_headers_arr_free(http_headers_arr_t* hs);
void httpp_req_free(http_req_t* req);
+#define HTTPP_IMPLEMENTATION
#ifdef HTTPP_IMPLEMENTATION
#define HTTP_DELIMITER "\r\n"
#define HTTP_DELIMITER_SIZE 2
#define HTTP_VERSION "HTTP/1.1"
-#define nomem() do { fprintf(stderr, "No memory, see ya!\n"); exit(1); } while (0)
-#define ltrim(str) \
- while(*(str) && isspace(*(str))) { \
- (str)++; \
- }
+#define trim(str) do { ltrim(str); rtrim(str); } while (0)
-#define rtrim(str) do { \
- char* end = (str) + strlen(str) - 1; \
- while (end >= (str) && isspace(*end)) { \
- *end = '\0'; \
- --end; \
+#define ltrim(str) do { \
+ char* __str = (str); \
+ while(*__str && isspace(*__str)) { \
+ __str++; \
} \
} while (0)
-static inline void* emalloc(size_t size)
-{
- void* ptr = malloc(size);
- if (!ptr)
- nomem();
-
- return ptr;
-}
-
-static inline void* erealloc(void* ptr, size_t size)
-{
- void* new_ptr = realloc(ptr, size);
- if (!new_ptr)
- nomem();
- return new_ptr;
-}
+#define rtrim(str) do { \
+ char* __str = (str); \
+ char* end = __str + strlen(__str) - 1; \
+ while (end >= __str && isspace(*end)) { \
+ *end-- = '\0'; \
+ } \
+ } while (0)
static int chop_until(char c, char** src, char* dest, size_t n)
{
@@ -113,7 +104,9 @@ static char* dchop_until(char c, char** src)
return NULL;
size_t chopped_size = pos - *src;
- char* out = (char*) emalloc(chopped_size + 1);
+ char* out = (char*) malloc(chopped_size + 1);
+ if (!out)
+ return NULL;
memcpy(out, *src, chopped_size);
out[chopped_size] = '\0';
@@ -134,11 +127,24 @@ const char* httpp_method_to_string(http_method_t m)
http_req_t* httpp_req_new()
{
- http_req_t* out = (http_req_t*) emalloc(sizeof(http_req_t));
+ http_req_t* out = (http_req_t*) malloc(sizeof(http_req_t));
+ if (!out)
+ return NULL;
+
+ out->headers = (http_headers_arr_t*) malloc(sizeof(http_headers_arr_t));
+ if (!out->headers) {
+ free(out);
+ return NULL;
+ }
- out->headers = (http_headers_arr_t*) emalloc(sizeof(http_headers_arr_t));
- out->headers->arr = (http_header_t*) emalloc(sizeof(http_header_t) * _HTTPP_INITIAL_HEADERS_ARR_CAP);
- out->headers->capacity = _HTTPP_INITIAL_HEADERS_ARR_CAP;
+ out->headers->arr = (http_header_t*) malloc(sizeof(http_header_t) * HTTPP_INITIAL_HEADERS_ARR_CAP);
+ if (!out->headers->arr) {
+ free(out->headers);
+ free(out);
+ return NULL;
+ }
+
+ out->headers->capacity = HTTPP_INITIAL_HEADERS_ARR_CAP;
out->headers->length = 0;
out->route = NULL;
out->body = NULL;
@@ -146,14 +152,19 @@ http_req_t* httpp_req_new()
return out;
}
-void httpp_req_free(http_req_t* req)
+void http_headers_arr_free(http_headers_arr_t* hs)
{
- if (!req) return;
-
- for (size_t i = 0; i < req->headers->length; i++) {
- free(req->headers->arr[i].name);
- free(req->headers->arr[i].value);
+ if (!hs) return;
+ for (size_t i = 0; i < hs->length; i++) {
+ free(hs->arr[i].name);
+ free(hs->arr[i].value);
}
+}
+
+void httpp_req_free(http_req_t* req)
+{
+ if (!req) return;
+ http_headers_arr_free(req->headers);
free(req->headers->arr);
free(req->headers);
@@ -162,51 +173,63 @@ void httpp_req_free(http_req_t* req)
free(req);
}
-void httpp_headers_append(http_headers_arr_t* hs, http_header_t header)
+int httpp_headers_append(http_headers_arr_t* hs, http_header_t header)
{
if (hs->length >= hs->capacity) {
size_t new_cap = hs->capacity * 2;
- hs->arr = (http_header_t*) erealloc(hs->arr, new_cap * sizeof(http_header_t));
+ if (new_cap <= hs->capacity) // Doesn't free on failure. Make a note about it
+ return HTTPP_ERRMEMRY;
+
+ hs->arr = (http_header_t*) realloc(hs->arr, new_cap * sizeof(http_header_t));
+ if (!hs->arr)
+ return HTTPP_ERRMEMRY;
+
hs->capacity = new_cap;
}
hs->arr[hs->length++] = header;
+ return 0;
}
int httpp_parse_header(http_headers_arr_t* hs, char* line)
{
char* delim_pos = strchr(line, ':');
if (!delim_pos)
- return 1;
+ return HTTPP_ERRLOGIC;
size_t name_len = (delim_pos - line);
if (name_len == 0)
- return 2;
+ return HTTPP_ERRLOGIC;
- char* name = (char*) emalloc(name_len + 1);
+ char* name = (char*) malloc(name_len + 1);
+ if (!name)
+ return HTTPP_ERRMEMRY;
+
memcpy(name, line, name_len);
name[name_len] = '\0';
+ trim(name);
char* value_start = delim_pos + 1;
- ltrim(value_start);
+ trim(value_start);
char* value = strdup(value_start);
if (!value)
- nomem();
+ return HTTPP_ERRMEMRY;
+
+ if (httpp_headers_append(hs, (http_header_t){name, value}) != 0)
+ return HTTPP_ERRMEMRY;
- httpp_headers_append(hs, (http_header_t){name, value});
return 0;
}
static int http_parse_start_line(char** itr, http_req_t* dest)
{
- char method_buf[_HTTPP_MAX_METHOD_LENGTH];
- char version_buf[_HTTPP_VERSION_BUFSIZE];
+ char method_buf[HTTPP_MAX_METHOD_LENGTH];
+ char version_buf[HTTPP_VERSION_BUFSIZE];
char* route;
ltrim(*itr);
-
- if (chop_until(' ', itr, method_buf, _HTTPP_MAX_METHOD_LENGTH) != 0)
+ if (chop_until(' ', itr, method_buf, HTTPP_MAX_METHOD_LENGTH) != 0)
return 1;
ltrim(*itr); // Route might have extra spaces at the bginning, for our implementation thats fine
@@ -214,12 +237,12 @@ static int http_parse_start_line(char** itr, http_req_t* dest)
return 1;
ltrim(*itr);
- if (chop_until('\n', itr, version_buf, _HTTPP_VERSION_BUFSIZE) != 0) {
+ if (chop_until('\n', itr, version_buf, HTTPP_VERSION_BUFSIZE) != 0) {
free(route);
return 1;
}
- rtrim(version_buf);
+ trim(version_buf);
if (strcmp(version_buf, HTTP_VERSION) != 0) {
free(route);
return 1;
@@ -236,7 +259,7 @@ http_req_t* httpp_parse_request(char* raw)
char* itr = raw;
char* end = raw + strlen(raw);
- char line[_HTTPP_LINE_BUFSIZE];
+ char line[HTTPP_LINE_BUFSIZE];
if (http_parse_start_line(&itr, out) != 0) {
httpp_req_free(out);
@@ -254,7 +277,7 @@ http_req_t* httpp_parse_request(char* raw)
break;
}
- if (line_size >= _HTTPP_LINE_BUFSIZE) {
+ if (line_size >= HTTPP_LINE_BUFSIZE) {
httpp_req_free(out);
return NULL;
}
diff --git a/test.c b/test.c
@@ -52,6 +52,20 @@ int main()
parsed = httpp_parse_request(req2);
print(parsed);
+ httpp_req_free(parsed);
+
+ char* req3 =
+ "POST /api/items HTTP/1.1\r\n"
+ "Host: api.example.com\r\n"
+ "User-Agent: MyClient/1.0\r\n"
+ "Content-Type: application/json; charset=utf-8\r\n"
+ "Content-Length: 106\r\n"
+ "X-Trace-ID: ;;--TRACE--;;\r\n"
+ "X-Feature-Flags: ,enable-new, ,\r\n"
+ "\r\n";
+
+ parsed = httpp_parse_request(req3);
+ print(parsed);
return 0;
}
\ No newline at end of file