comparison 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
comparison
equal deleted inserted replaced
91:19cccf6e866a 92:655ea0b661fd
102 void *p_response_header = Dowa_Arena_Allocate(p_response_arena, (size_t)1024*5); // 5Kb 102 void *p_response_header = Dowa_Arena_Allocate(p_response_arena, (size_t)1024*5); // 5Kb
103 if (!p_response_header) { perror("Dowa_Arena_Allocate"); goto clean_up; } 103 if (!p_response_header) { perror("Dowa_Arena_Allocate"); goto clean_up; }
104 104
105 // Parse request headers into hashmap using arena 105 // Parse request headers into hashmap using arena
106 Seobeo_Request_Entry *p_req_map = NULL; 106 Seobeo_Request_Entry *p_req_map = NULL;
107 if (Seobeo_Web_Header_Parse(p_cli_handle, &p_req_map, p_request_arena) != 0) 107 int parse_result = Seobeo_Web_Header_Parse(p_cli_handle, &p_req_map, p_request_arena);
108 { 108
109 // Treat EAGAIN (return code 1) as success - headers were parsed, body may still be coming
110 if (parse_result != 0 && parse_result != 1)
111 {
112 printf("ERROR: Seobeo_Web_Header_Parse failed with code %d\n", parse_result);
113 fflush(stdout);
109 Seobeo_Web_Header_Generate(p_response_header, 114 Seobeo_Web_Header_Generate(p_response_header,
110 HTTP_BAD_REQUEST, 115 HTTP_BAD_REQUEST,
111 "text/plain", 0); 116 "text/plain", 0);
112 Seobeo_Handle_Queue(p_cli_handle, 117 Seobeo_Handle_Queue(p_cli_handle,
113 (const uint8*)p_response_header, 118 (const uint8*)p_response_header,
114 (uint32)strlen(p_response_header)); 119 (uint32)strlen(p_response_header));
115 Seobeo_Handle_Flush(p_cli_handle); 120 Seobeo_Handle_Flush(p_cli_handle);
116 goto clean_up; 121 goto clean_up;
117 } 122 }
118 123
124 printf("DEBUG: Parse completed with code %d\n", parse_result);
125 fflush(stdout);
126
119 // Extract method (GET, POST, etc.) 127 // Extract method (GET, POST, etc.)
120 void *p_method_kv = Dowa_HashMap_Get_Ptr(p_req_map, "HTTP_Method"); 128 void *p_method_kv = Dowa_HashMap_Get_Ptr(p_req_map, "HTTP_Method");
121 const char *method = p_method_kv ? ((Seobeo_Request_Entry*)p_method_kv)->value : NULL; 129 const char *method = p_method_kv ? ((Seobeo_Request_Entry*)p_method_kv)->value : NULL;
122 130
131 printf("DEBUG: Parsed request, method=%s\n", method ? method : "NULL");
132 fflush(stdout);
133
123 if (!method) 134 if (!method)
124 { 135 {
136 printf("ERROR: No HTTP method found in request\n");
137 fflush(stdout);
125 Seobeo_Web_Header_Generate(p_response_header, 138 Seobeo_Web_Header_Generate(p_response_header,
126 HTTP_BAD_REQUEST, 139 HTTP_BAD_REQUEST,
127 "text/plain", 0); 140 "text/plain", 0);
128 Seobeo_Handle_Queue(p_cli_handle, 141 Seobeo_Handle_Queue(p_cli_handle,
129 (const uint8*)p_response_header, 142 (const uint8*)p_response_header,
275 // 2) Parse request‐line "METHOD SP PATH SP VERSION CRLF" 288 // 2) Parse request‐line "METHOD SP PATH SP VERSION CRLF"
276 char *buf = (char*)p_handle->read_buffer; 289 char *buf = (char*)p_handle->read_buffer;
277 char *hdr_end = strstr(buf, "\r\n\r\n"); 290 char *hdr_end = strstr(buf, "\r\n\r\n");
278 size_t hdr_len = hdr_end - buf + 4; 291 size_t hdr_len = hdr_end - buf + 4;
279 292
293 // Debug: Print the first line of the request
294 char *first_line_end = strstr(buf, "\r\n");
295 if (first_line_end)
296 {
297 size_t first_line_len = first_line_end - buf;
298 printf("DEBUG: Request line (first %zu bytes): '", first_line_len > 200 ? 200 : first_line_len);
299 fwrite(buf, 1, first_line_len > 200 ? 200 : first_line_len, stdout);
300 printf("'\n");
301 fflush(stdout);
302 }
303
280 // This seems kinda bad ? 304 // This seems kinda bad ?
281 char method[16], path[256], version[16]; 305 char method[16], path[256], version[16];
282 if (sscanf(buf, "%15s %255s %15s", method, path, version) != 3) 306 int scan_result = sscanf(buf, "%15s %255s %15s", method, path, version);
283 { 307 printf("DEBUG: sscanf returned %d (method='%s', path='%s', version='%s')\n",
308 scan_result,
309 scan_result >= 1 ? method : "N/A",
310 scan_result >= 2 ? path : "N/A",
311 scan_result >= 3 ? version : "N/A");
312 fflush(stdout);
313
314 if (scan_result != 3)
315 {
316 printf("ERROR: Failed to parse request line\n");
317 fflush(stdout);
284 return -1; 318 return -1;
285 } 319 }
286 320
287 // Copy strings to arena and store in hashmap 321 // Copy strings to arena and store in hashmap
322 printf("DEBUG: Allocating method_copy\n");
323 fflush(stdout);
288 char *method_copy = Dowa_Arena_Allocate(p_arena, strlen(method) + 1); 324 char *method_copy = Dowa_Arena_Allocate(p_arena, strlen(method) + 1);
289 if (!method_copy) return -1; 325 if (!method_copy) { printf("ERROR: Failed to allocate method_copy\n"); return -1; }
290 strcpy(method_copy, method); 326 strcpy(method_copy, method);
291 327
328 printf("DEBUG: Allocating version_copy\n");
329 fflush(stdout);
292 char *version_copy = Dowa_Arena_Allocate(p_arena, strlen(version) + 1); 330 char *version_copy = Dowa_Arena_Allocate(p_arena, strlen(version) + 1);
293 if (!version_copy) return -1; 331 if (!version_copy) { printf("ERROR: Failed to allocate version_copy\n"); return -1; }
294 strcpy(version_copy, version); 332 strcpy(version_copy, version);
295 333
334 printf("DEBUG: Pushing HTTP_Method and Version to map\n");
335 fflush(stdout);
296 Dowa_HashMap_Push_Arena(*pp_map, "HTTP_Method", method_copy, p_arena); 336 Dowa_HashMap_Push_Arena(*pp_map, "HTTP_Method", method_copy, p_arena);
297 Dowa_HashMap_Push_Arena(*pp_map, "Version", version_copy, p_arena); 337 Dowa_HashMap_Push_Arena(*pp_map, "Version", version_copy, p_arena);
338 printf("DEBUG: Map now has %zu entries\n", Dowa_Array_Length(*pp_map));
339 fflush(stdout);
298 340
299 // 1) Separate raw path and query string 341 // 1) Separate raw path and query string
300 char *raw_path = path; 342 char *raw_path = path;
301 char *query_start = strchr(raw_path, '?'); 343 char *query_start = strchr(raw_path, '?');
302 char *query_str = NULL; 344 char *query_str = NULL;
392 void *p_cl_kv = Dowa_HashMap_Get_Ptr(*pp_map, "Content-Length"); 434 void *p_cl_kv = Dowa_HashMap_Get_Ptr(*pp_map, "Content-Length");
393 if (p_cl_kv) 435 if (p_cl_kv)
394 { 436 {
395 const char *content_length_str = ((Seobeo_Request_Entry*)p_cl_kv)->value; 437 const char *content_length_str = ((Seobeo_Request_Entry*)p_cl_kv)->value;
396 size_t body_len = atoi(content_length_str); 438 size_t body_len = atoi(content_length_str);
397 while (p_handle->read_buffer_len < body_len) 439
398 { 440 printf("DEBUG: Content-Length=%zu, reading body in chunks...\n", body_len);
399 int r = Seobeo_Handle_Read(p_handle); 441 fflush(stdout);
400 if (r < 0) return -1; 442
401 if (r == 0) return 1; // wait for more data 443 // Allocate buffer for entire body
402 }
403
404 char *body = Dowa_Arena_Allocate(p_arena, body_len + 1); 444 char *body = Dowa_Arena_Allocate(p_arena, body_len + 1);
405 if (!body) return -1; 445 if (!body)
406 memcpy(body, p_handle->read_buffer, body_len); 446 {
447 printf("ERROR: Failed to allocate %zu bytes for body\n", body_len);
448 fflush(stdout);
449 return -1;
450 }
451
452 size_t total_read = 0;
453
454 // Read body in chunks
455 while (total_read < body_len)
456 {
457 // Copy what's currently in the read buffer
458 size_t available = p_handle->read_buffer_len;
459 size_t to_copy = (body_len - total_read) < available ? (body_len - total_read) : available;
460
461 if (to_copy > 0)
462 {
463 memcpy(body + total_read, p_handle->read_buffer, to_copy);
464 total_read += to_copy;
465 Seobeo_Handle_Consume(p_handle, (uint32)to_copy);
466
467 printf("DEBUG: Copied %zu bytes, total %zu/%zu\n", to_copy, total_read, body_len);
468 fflush(stdout);
469 }
470
471 // If we still need more data, read another chunk
472 if (total_read < body_len)
473 {
474 int r = Seobeo_Handle_Read(p_handle);
475 if (r < 0)
476 {
477 printf("ERROR: Read failed with %d\n", r);
478 fflush(stdout);
479 return -1;
480 }
481 if (r == 0)
482 {
483 // No data available yet, continue waiting
484 // printf("DEBUG: Waiting for more data... (have %zu/%zu bytes)\n", total_read, body_len);
485 fflush(stdout);
486 continue;
487 }
488 }
489 }
490
407 body[body_len] = '\0'; 491 body[body_len] = '\0';
492 printf("DEBUG: Body fully received (%zu bytes)\n", body_len);
493 fflush(stdout);
408 494
409 // Body is arena-allocated 495 // Body is arena-allocated
410 Dowa_HashMap_Push_Arena(*pp_map, "Body", body, p_arena); 496 Dowa_HashMap_Push_Arena(*pp_map, "Body", body, p_arena);
411
412 Seobeo_Handle_Consume(p_handle, (uint32)body_len);
413 } 497 }
414 498
415 return 0; // success; map now holds Method, Path, Version, headers, and optional Body 499 return 0; // success; map now holds Method, Path, Version, headers, and optional Body
416 } 500 }
417 501