Mercurial
comparison seobeo/s_web.c @ 72:4532ce6d9eb8
[Seobeo] Added router to the server logic. Few dowa string manipulation logics.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 29 Dec 2025 07:50:07 -0800 |
| parents | 75de5903355c |
| children | 35b1abc37969 |
comparison
equal
deleted
inserted
replaced
| 71:75de5903355c | 72:4532ce6d9eb8 |
|---|---|
| 93 Seobeo_Cache_Entry *p_html_cache) | 93 Seobeo_Cache_Entry *p_html_cache) |
| 94 { | 94 { |
| 95 Dowa_Arena *p_request_arena = Dowa_Arena_Create(1*1024*1024); // 1MB for request parsing | 95 Dowa_Arena *p_request_arena = Dowa_Arena_Create(1*1024*1024); // 1MB for request parsing |
| 96 if (!p_request_arena) { perror("Dowa_Arena_Create request"); goto clean_up; } | 96 if (!p_request_arena) { perror("Dowa_Arena_Create request"); goto clean_up; } |
| 97 | 97 |
| 98 Dowa_Arena *p_response_arena = Dowa_Arena_Create(1*1024*1024); // 1MB for response | 98 Dowa_Arena *p_response_arena = Dowa_Arena_Create(5*1024*1024); // 1MB for response |
| 99 if (!p_response_arena) { perror("Dowa_Arena_Create response"); goto clean_up; } | 99 if (!p_response_arena) { perror("Dowa_Arena_Create response"); goto clean_up; } |
| 100 | 100 |
| 101 void *p_response_header = Dowa_Arena_Allocate(p_response_arena, (size_t)1024*5); // 5Kb | 101 void *p_response_header = Dowa_Arena_Allocate(p_response_arena, (size_t)1024*5); // 5Kb |
| 102 if (!p_response_header) { perror("Dowa_Arena_Allocate"); goto clean_up; } | 102 if (!p_response_header) { perror("Dowa_Arena_Allocate"); goto clean_up; } |
| 103 | 103 |
| 129 (uint32)strlen(p_response_header)); | 129 (uint32)strlen(p_response_header)); |
| 130 Seobeo_Handle_Flush(p_cli_handle); | 130 Seobeo_Handle_Flush(p_cli_handle); |
| 131 goto clean_up; | 131 goto clean_up; |
| 132 } | 132 } |
| 133 | 133 |
| 134 // --- Handle different HTTP methods --- | 134 // Extract path |
| 135 void *p_path_kv = Dowa_HashMap_Get_Ptr(p_req_map, "Path"); | |
| 136 const char *path = p_path_kv ? ((Seobeo_Request_Entry*)p_path_kv)->value : "/"; | |
| 137 | |
| 138 // --- Try to match API route first --- | |
| 139 Seobeo_Route_Handler handler = Seobeo_Router_Find_Handler(method, path, &p_req_map, p_request_arena); | |
| 140 | |
| 141 if (handler != NULL) | |
| 142 { | |
| 143 // Call the API handler | |
| 144 Seobeo_Request_Entry *p_response_map = handler(p_req_map, p_response_arena); | |
| 145 | |
| 146 // Send the response | |
| 147 Seobeo_Router_Send_Response(p_cli_handle, p_response_map, p_response_arena); | |
| 148 goto clean_up; | |
| 149 } | |
| 150 | |
| 151 // --- Handle different HTTP methods (static files fallback) --- | |
| 135 if (strcmp(method, "GET") == 0) | 152 if (strcmp(method, "GET") == 0) |
| 136 { | 153 { |
| 137 void *p_kv = Dowa_HashMap_Get_Ptr(p_req_map, "Path"); | 154 void *p_kv = Dowa_HashMap_Get_Ptr(p_req_map, "Path"); |
| 138 const char *path = p_kv ? ((Seobeo_Request_Entry*)p_kv)->value : NULL; | 155 const char *path = p_kv ? ((Seobeo_Request_Entry*)p_kv)->value : NULL; |
| 139 char *file_path = Dowa_Arena_Allocate(p_response_arena, (size_t)5 * 1024); // 5Kb only for path | 156 char *file_path = Dowa_Arena_Allocate(p_response_arena, (size_t)5 * 1024); // 5Kb only for path |
| 151 snprintf(file_path, 512, "%.*s/index.html", (int)(L-1), path+1); | 168 snprintf(file_path, 512, "%.*s/index.html", (int)(L-1), path+1); |
| 152 else | 169 else |
| 153 snprintf(file_path, 512, "%.*s", (int)(L-1), path+1); | 170 snprintf(file_path, 512, "%.*s", (int)(L-1), path+1); |
| 154 } | 171 } |
| 155 else | 172 else |
| 156 { | |
| 157 strcpy(file_path, path); | 173 strcpy(file_path, path); |
| 158 } | |
| 159 } | 174 } |
| 160 | 175 |
| 161 // Check if file is in cache, load if not | 176 // Check if file is in cache, load if not |
| 162 void *p_file_kv = Dowa_HashMap_Get_Ptr(p_html_cache, file_path); | 177 void *p_file_kv = Dowa_HashMap_Get_Ptr(p_html_cache, file_path); |
| 163 const char *file_content = NULL; | 178 const char *file_content = NULL; |
| 169 file_content = ((Seobeo_Cache_Entry*)p_file_kv)->value; | 184 file_content = ((Seobeo_Cache_Entry*)p_file_kv)->value; |
| 170 body_size = strlen(file_content); | 185 body_size = strlen(file_content); |
| 171 } | 186 } |
| 172 else | 187 else |
| 173 { | 188 { |
| 174 // Load from disk and cache | |
| 175 file_content = Seobeo_Web_LoadFile(file_path, &body_size); | 189 file_content = Seobeo_Web_LoadFile(file_path, &body_size); |
| 176 if (file_content) | 190 if (file_content) |
| 177 { | |
| 178 Dowa_HashMap_Push(p_html_cache, file_path, file_content); | 191 Dowa_HashMap_Push(p_html_cache, file_path, file_content); |
| 179 } | |
| 180 } | 192 } |
| 181 | 193 |
| 182 if (!file_content) | 194 if (!file_content) |
| 183 { | 195 { |
| 184 Seobeo_Web_Header_Generate(p_response_header, | 196 Seobeo_Web_Header_Generate(p_response_header, |
| 189 (uint32)strlen(p_response_header)); | 201 (uint32)strlen(p_response_header)); |
| 190 Seobeo_Handle_Flush(p_cli_handle); | 202 Seobeo_Handle_Flush(p_cli_handle); |
| 191 goto clean_up; | 203 goto clean_up; |
| 192 } | 204 } |
| 193 | 205 |
| 206 // Serve static file | |
| 194 const char *mime = "application/octet-stream"; | 207 const char *mime = "application/octet-stream"; |
| 195 if (strstr(file_path, ".html")) mime = "text/html; charset=utf-8"; | 208 if (strstr(file_path, ".html")) mime = "text/html; charset=utf-8"; |
| 196 else if (strstr(file_path, ".css")) mime = "text/css"; | 209 else if (strstr(file_path, ".css")) mime = "text/css"; |
| 197 else if (strstr(file_path, ".js")) mime = "application/javascript"; | 210 else if (strstr(file_path, ".js")) mime = "application/javascript"; |
| 198 else if (strstr(file_path, ".png")) mime = "image/png"; | 211 else if (strstr(file_path, ".png")) mime = "image/png"; |
| 216 (const uint8*)file_content, | 229 (const uint8*)file_content, |
| 217 (uint32)body_size); | 230 (uint32)body_size); |
| 218 Seobeo_Handle_Flush(p_cli_handle); | 231 Seobeo_Handle_Flush(p_cli_handle); |
| 219 printf("DONE\n\n\n"); | 232 printf("DONE\n\n\n"); |
| 220 } | 233 } |
| 221 else if (strcmp(method, "POST") == 0) | |
| 222 { | |
| 223 // --- TODO: Add POST logic here --- | |
| 224 Seobeo_Web_Header_Generate(p_response_header, | |
| 225 HTTP_NOT_FOUND, | |
| 226 "text/plain", 0); | |
| 227 Seobeo_Handle_Queue(p_cli_handle, | |
| 228 (const uint8*)p_response_header, | |
| 229 (uint32)strlen(p_response_header)); | |
| 230 Seobeo_Handle_Flush(p_cli_handle); | |
| 231 } | |
| 232 else if (strcmp(method, "PUT") == 0) | |
| 233 { | |
| 234 // --- TODO: Add PUT logic here --- | |
| 235 Seobeo_Web_Header_Generate(p_response_header, | |
| 236 HTTP_NOT_FOUND, | |
| 237 "text/plain", 0); | |
| 238 Seobeo_Handle_Queue(p_cli_handle, | |
| 239 (const uint8*)p_response_header, | |
| 240 (uint32)strlen(p_response_header)); | |
| 241 Seobeo_Handle_Flush(p_cli_handle); | |
| 242 } | |
| 243 else if (strcmp(method, "DELETE") == 0) | |
| 244 { | |
| 245 // --- TODO: Add DELETE logic here --- | |
| 246 Seobeo_Web_Header_Generate(p_response_header, | |
| 247 HTTP_NOT_FOUND, | |
| 248 "text/plain", 0); | |
| 249 Seobeo_Handle_Queue(p_cli_handle, | |
| 250 (const uint8*)p_response_header, | |
| 251 (uint32)strlen(p_response_header)); | |
| 252 Seobeo_Handle_Flush(p_cli_handle); | |
| 253 } | |
| 254 else | 234 else |
| 255 { | 235 { |
| 256 // Unknown or unsupported method | |
| 257 Seobeo_Web_Header_Generate(p_response_header, | 236 Seobeo_Web_Header_Generate(p_response_header, |
| 258 HTTP_FORBIDDEN, | 237 HTTP_FORBIDDEN, |
| 259 "text/plain", 0); | 238 "text/plain", 0); |
| 260 Seobeo_Handle_Queue(p_cli_handle, | 239 Seobeo_Handle_Queue(p_cli_handle, |
| 261 (const uint8*)p_response_header, | 240 (const uint8*)p_response_header, |
| 267 clean_up: | 246 clean_up: |
| 268 printf("clean up\n\n"); | 247 printf("clean up\n\n"); |
| 269 if (p_cli_handle) | 248 if (p_cli_handle) |
| 270 Seobeo_Handle_Destroy(p_cli_handle); | 249 Seobeo_Handle_Destroy(p_cli_handle); |
| 271 if (p_request_arena) | 250 if (p_request_arena) |
| 272 Dowa_Arena_Destroy(p_request_arena); | 251 Dowa_Arena_Free(p_request_arena); |
| 273 if (p_response_arena) | 252 if (p_response_arena) |
| 274 Dowa_Arena_Destroy(p_response_arena); | 253 Dowa_Arena_Free(p_response_arena); |
| 275 return; | 254 return; |
| 276 } | 255 } |
| 277 | 256 |
| 278 | 257 |
| 279 int Seobeo_Web_Header_Parse(Seobeo_Handle *p_handle, Seobeo_Request_Entry **pp_map, Dowa_Arena *p_arena) | 258 int Seobeo_Web_Header_Parse(Seobeo_Handle *p_handle, Seobeo_Request_Entry **pp_map, Dowa_Arena *p_arena) |
| 559 // peer closed; we’ve got everything | 538 // peer closed; we’ve got everything |
| 560 printf("\n\nCLOSED\n\n"); | 539 printf("\n\nCLOSED\n\n"); |
| 561 break; | 540 break; |
| 562 }else | 541 }else |
| 563 { | 542 { |
| 564 Dowa_Arena_Destroy(p_request_arena); | 543 Dowa_Arena_Free(p_request_arena); |
| 565 Seobeo_Handle_Destroy(h); | 544 Seobeo_Handle_Destroy(h); |
| 566 return -1; | 545 return -1; |
| 567 } | 546 } |
| 568 } | 547 } |
| 569 | 548 |
| 570 // Debug | 549 // Debug |
| 571 printf("Request body %s", p_request_body); | 550 printf("Request body %s", p_request_body); |
| 572 Dowa_Arena_Destroy(p_request_arena); | 551 Dowa_Arena_Free(p_request_arena); |
| 573 Seobeo_Handle_Destroy(h); | 552 Seobeo_Handle_Destroy(h); |
| 574 return 0; | 553 return 0; |
| 575 } | 554 } |