diff seobeo/s_web.c @ 92:655ea0b661fd

[Seobeo] Added few endpoints for handling files. [Dowa] Added few functions for random number and generating uuids
author June Park <parkjune1995@gmail.com>
date Fri, 02 Jan 2026 17:47:10 -0800
parents 19cccf6e866a
children 70401cf61e97
line wrap: on
line diff
--- a/seobeo/s_web.c	Thu Jan 01 16:34:51 2026 -0800
+++ b/seobeo/s_web.c	Fri Jan 02 17:47:10 2026 -0800
@@ -104,8 +104,13 @@
 
   // Parse request headers into hashmap using arena
   Seobeo_Request_Entry *p_req_map = NULL;
-  if (Seobeo_Web_Header_Parse(p_cli_handle, &p_req_map, p_request_arena) != 0)
+  int parse_result = Seobeo_Web_Header_Parse(p_cli_handle, &p_req_map, p_request_arena);
+
+  // Treat EAGAIN (return code 1) as success - headers were parsed, body may still be coming
+  if (parse_result != 0 && parse_result != 1)
   {
+    printf("ERROR: Seobeo_Web_Header_Parse failed with code %d\n", parse_result);
+    fflush(stdout);
     Seobeo_Web_Header_Generate(p_response_header,
                                HTTP_BAD_REQUEST,
                                "text/plain", 0);
@@ -116,12 +121,20 @@
     goto clean_up;
   }
 
+  printf("DEBUG: Parse completed with code %d\n", parse_result);
+  fflush(stdout);
+
   // Extract method (GET, POST, etc.)
   void *p_method_kv = Dowa_HashMap_Get_Ptr(p_req_map, "HTTP_Method");
   const char *method = p_method_kv ? ((Seobeo_Request_Entry*)p_method_kv)->value : NULL;
 
+  printf("DEBUG: Parsed request, method=%s\n", method ? method : "NULL");
+  fflush(stdout);
+
   if (!method)
   {
+    printf("ERROR: No HTTP method found in request\n");
+    fflush(stdout);
     Seobeo_Web_Header_Generate(p_response_header,
                                HTTP_BAD_REQUEST,
                                "text/plain", 0);
@@ -277,24 +290,53 @@
   char *hdr_end   = strstr(buf, "\r\n\r\n");
   size_t hdr_len  = hdr_end - buf + 4;
 
+  // Debug: Print the first line of the request
+  char *first_line_end = strstr(buf, "\r\n");
+  if (first_line_end)
+  {
+    size_t first_line_len = first_line_end - buf;
+    printf("DEBUG: Request line (first %zu bytes): '", first_line_len > 200 ? 200 : first_line_len);
+    fwrite(buf, 1, first_line_len > 200 ? 200 : first_line_len, stdout);
+    printf("'\n");
+    fflush(stdout);
+  }
+
   // This seems kinda bad ?
   char method[16], path[256], version[16];
-  if (sscanf(buf, "%15s %255s %15s", method, path, version) != 3)
+  int scan_result = sscanf(buf, "%15s %255s %15s", method, path, version);
+  printf("DEBUG: sscanf returned %d (method='%s', path='%s', version='%s')\n",
+         scan_result,
+         scan_result >= 1 ? method : "N/A",
+         scan_result >= 2 ? path : "N/A",
+         scan_result >= 3 ? version : "N/A");
+  fflush(stdout);
+
+  if (scan_result != 3)
   {
+    printf("ERROR: Failed to parse request line\n");
+    fflush(stdout);
     return -1;
   }
 
   // Copy strings to arena and store in hashmap
+  printf("DEBUG: Allocating method_copy\n");
+  fflush(stdout);
   char *method_copy = Dowa_Arena_Allocate(p_arena, strlen(method) + 1);
-  if (!method_copy) return -1;
+  if (!method_copy) { printf("ERROR: Failed to allocate method_copy\n"); return -1; }
   strcpy(method_copy, method);
 
+  printf("DEBUG: Allocating version_copy\n");
+  fflush(stdout);
   char *version_copy = Dowa_Arena_Allocate(p_arena, strlen(version) + 1);
-  if (!version_copy) return -1;
+  if (!version_copy) { printf("ERROR: Failed to allocate version_copy\n"); return -1; }
   strcpy(version_copy, version);
 
+  printf("DEBUG: Pushing HTTP_Method and Version to map\n");
+  fflush(stdout);
   Dowa_HashMap_Push_Arena(*pp_map, "HTTP_Method", method_copy, p_arena);
   Dowa_HashMap_Push_Arena(*pp_map, "Version", version_copy, p_arena);
+  printf("DEBUG: Map now has %zu entries\n", Dowa_Array_Length(*pp_map));
+  fflush(stdout);
 
   // 1) Separate raw path and query string
   char *raw_path = path;  
@@ -394,22 +436,64 @@
   {
     const char *content_length_str = ((Seobeo_Request_Entry*)p_cl_kv)->value;
     size_t body_len = atoi(content_length_str);
-    while (p_handle->read_buffer_len < body_len)
+
+    printf("DEBUG: Content-Length=%zu, reading body in chunks...\n", body_len);
+    fflush(stdout);
+
+    // Allocate buffer for entire body
+    char *body = Dowa_Arena_Allocate(p_arena, body_len + 1);
+    if (!body)
     {
-      int r = Seobeo_Handle_Read(p_handle);
-      if (r < 0)   return -1;
-      if (r ==  0) return 1;       // wait for more data
+      printf("ERROR: Failed to allocate %zu bytes for body\n", body_len);
+      fflush(stdout);
+      return -1;
     }
 
-    char *body = Dowa_Arena_Allocate(p_arena, body_len + 1);
-    if (!body) return -1;
-    memcpy(body, p_handle->read_buffer, body_len);
+    size_t total_read = 0;
+
+    // Read body in chunks
+    while (total_read < body_len)
+    {
+      // Copy what's currently in the read buffer
+      size_t available = p_handle->read_buffer_len;
+      size_t to_copy = (body_len - total_read) < available ? (body_len - total_read) : available;
+
+      if (to_copy > 0)
+      {
+        memcpy(body + total_read, p_handle->read_buffer, to_copy);
+        total_read += to_copy;
+        Seobeo_Handle_Consume(p_handle, (uint32)to_copy);
+
+        printf("DEBUG: Copied %zu bytes, total %zu/%zu\n", to_copy, total_read, body_len);
+        fflush(stdout);
+      }
+
+      // If we still need more data, read another chunk
+      if (total_read < body_len)
+      {
+        int r = Seobeo_Handle_Read(p_handle);
+        if (r < 0)
+        {
+          printf("ERROR: Read failed with %d\n", r);
+          fflush(stdout);
+          return -1;
+        }
+        if (r == 0)
+        {
+          // No data available yet, continue waiting
+          // printf("DEBUG: Waiting for more data... (have %zu/%zu bytes)\n", total_read, body_len);
+          fflush(stdout);
+          continue;
+        }
+      }
+    }
+
     body[body_len] = '\0';
+    printf("DEBUG: Body fully received (%zu bytes)\n", body_len);
+    fflush(stdout);
 
     // Body is arena-allocated
     Dowa_HashMap_Push_Arena(*pp_map, "Body", body, p_arena);
-
-    Seobeo_Handle_Consume(p_handle, (uint32)body_len);
   }
 
   return 0;  // success; map now holds Method, Path, Version, headers, and optional Body