comparison seobeo/s_web.c @ 18:fa2b8af609d9

[Seobeo] Fixed a bug with pathing. Support SSL.
author June Park <parkjune1995@gmail.com>
date Mon, 06 Oct 2025 08:21:34 -0700
parents d97ec3ded2ae
children 875bb6e10db7
comparison
equal deleted inserted replaced
17:d97ec3ded2ae 18:fa2b8af609d9
6 return sprintf( 6 return sprintf(
7 buffer, 7 buffer,
8 "GET %s HTTP/1.1\r\n" 8 "GET %s HTTP/1.1\r\n"
9 "Host: %s\r\n" 9 "Host: %s\r\n"
10 "Connection: close\r\n" 10 "Connection: close\r\n"
11 "accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\n"
12 "accept-language: en-GB,en;q=0.9,en-US;q=0.8,ko;q=0.7\r\n"
13 "if-modified-since: Sat, 02 Aug 2025 22:51:58 GMT\r\n"
14 "if-none-match: W/\"688e968e-5700\"\r\n"
15 "priority: u=0, i\r\n"
16 "sec-ch-ua: \"Chromium\";v=\"140\", \"Not=A?Brand\";v=\"24\", \"Google Chrome\";v=\"140\"\r\n"
17 "sec-ch-ua-mobile: 0\r\n"
18 "sec-ch-ua-platform: \"macOS\"\r\n"
19 "sec-fetch-dest: document\r\n"
20 "sec-fetch-mode: navigate\r\n"
21 "sec-fetch-site: none\r\n"
22 "sec-fetch-user: 1\r\n"
23 "upgrade-insecure-requests: 1\r\n"
11 "\r\n", 24 "\r\n",
12 path, host 25 path, host
13 ); 26 );
14 } 27 }
15 28
31 default: status_text = "Unknown"; break; 44 default: status_text = "Unknown"; break;
32 } 45 }
33 46
34 sprintf( 47 sprintf(
35 buffer, 48 buffer,
36 "HTTP/2.2 %d %s\r\n" 49 "HTTP/1.1 %d %s\r\n"
37 "Content-Type: %s\r\n" 50 "Content-Type: %s\r\n"
38 "Content-Length: %d\r\n" 51 "Content-Length: %d\r\n"
39 "Connection: close\r\n" 52 "Connection: close\r\n"
40 "\r\n", 53 "\r\n",
41 status, status_text, content_type, content_length 54 status, status_text, content_type, content_length
69 (uint32)strlen(p_response_header)); 82 (uint32)strlen(p_response_header));
70 Seobeo_Handle_Flush(p_cli_handle); 83 Seobeo_Handle_Flush(p_cli_handle);
71 goto clean_up; 84 goto clean_up;
72 } 85 }
73 86
74 Dowa_HashMap_Print(p_req_map); 87 // DEBUG
88 // Dowa_HashMap_Print(p_req_map);
75 89
76 const char *path = (const char*)Dowa_HashMap_Get(p_req_map, "Path"); 90 const char *path = (const char*)Dowa_HashMap_Get(p_req_map, "Path");
77
78 char *file_path = Dowa_Arena_Allocate(p_response_arena, (size_t)512); 91 char *file_path = Dowa_Arena_Allocate(p_response_arena, (size_t)512);
79 92
80 if (!path || strcmp(path, "/") == 0) 93 if (!path || strcmp(path, "/") == 0)
81 { 94 {
82 strcpy(file_path, "index.html"); 95 strcpy(file_path, "index.html");
83 } 96 }else
84 else
85 { 97 {
86 size_t L = strlen(path); 98 size_t L = strlen(path);
87 // strip leading '/' 99 // strip leading '/'
88 if (path[0] == '/') 100 if (path[0] == '/')
89 { 101 {
90 if (strchr(path, '.') == NULL) 102 if (strchr(path, '.') == NULL)
91 snprintf(file_path, 512, "%.*s/index.html", (int)(L-1), path+1); 103 snprintf(file_path, 512, "%.*s/index.html", (int)(L-1), path+1);
92 else 104 else
93 snprintf(file_path, 512, "%.*s", (int)(L-1), path+1); 105 snprintf(file_path, 512, "%.*s", (int)(L-1), path+1);
94 } 106 }else
95 else
96 { 107 {
97 // Probably never get here? 108 // Probably never get here?
98 strcpy(file_path, path); 109 strcpy(file_path, path);
99 } 110 }
100 } 111 }
101 112
113 // DEBUG
102 // printf("\n\nfile_path: %s\n", file_path); 114 // printf("\n\nfile_path: %s\n", file_path);
103 115
104 // Recursively go though the path until it gets to a file 116 // Recursively go though the path until it gets to a file
105 while ((slash = strchr(file_path, '/'))) 117 while ((slash = strchr(file_path, '/')))
106 { 118 {
107 *slash = '\0'; // e.g. file_path="foo", slash+1="index.html" 119 *slash = '\0'; // e.g. file_path="foo", slash+1="index.html"
108 char *dir = file_path; // "foo" 120 char *dir = file_path; // "foo"
109 file_path = slash + 1; // "index.html" 121 file_path = slash + 1; // "index.html"
110 122
123 printf("\n\nDirectory: %s\n\n", dir);
124
111 p_current = Dowa_HashMap_Get(p_current, dir); 125 p_current = Dowa_HashMap_Get(p_current, dir);
112 if (!p_current) { perror("No value"); goto clean_up; } 126 if (!p_current)
127 {
128 fprintf(stderr, "No value in hashmap key: %s\n\n", dir);
129 Seobeo_Web_GenerateResponseHeader(p_response_header,
130 HTTP_NOT_FOUND,
131 "text/html", 0);
132 Seobeo_Handle_Queue(p_cli_handle,
133 (const uint8*)p_response_header,
134 (uint32)strlen(p_response_header));
135 Seobeo_Handle_Flush(p_cli_handle);
136 goto clean_up;
137 }
113 } 138 }
114 139
115 size_t pos = Dowa_HashMap_GetPosition(p_current, file_path); 140 size_t pos = Dowa_HashMap_GetPosition(p_current, file_path);
116 entry = p_current->entries[pos]; 141 entry = p_current->entries[pos];
117 142
139 else if (strstr(file_path, ".svg")) mime = "image/svg+xml"; 164 else if (strstr(file_path, ".svg")) mime = "image/svg+xml";
140 else if (strstr(file_path, ".ico")) mime = "image/x-icon"; 165 else if (strstr(file_path, ".ico")) mime = "image/x-icon";
141 else if (strstr(file_path, ".json")) mime = "application/json"; 166 else if (strstr(file_path, ".json")) mime = "application/json";
142 167
143 size_t body_size = entry->capacity; 168 size_t body_size = entry->capacity;
169 printf("key: %s\n\n", entry->key);
170 printf("Body Size: %zu\n\n", body_size);
144 Seobeo_Web_GenerateResponseHeader(p_response_header, 171 Seobeo_Web_GenerateResponseHeader(p_response_header,
145 HTTP_OK, 172 HTTP_OK,
146 mime, 173 mime,
147 body_size); 174 body_size);
175
176 printf("response header: %s, data: %d\n\n", p_response_header, (uint32)strlen(p_response_header));
148 Seobeo_Handle_Queue(p_cli_handle, 177 Seobeo_Handle_Queue(p_cli_handle,
149 (const uint8*)p_response_header, 178 (const uint8*)p_response_header,
150 (uint32)strlen(p_response_header)); 179 (uint32)strlen(p_response_header));
180
181 printf("response body data: %d\n\n", (uint32)body_size);
151 Seobeo_Handle_Queue(p_cli_handle, 182 Seobeo_Handle_Queue(p_cli_handle,
152 (const uint8*)entry->buffer, 183 (const uint8*)entry->buffer,
153 (uint32)body_size); 184 (uint32)body_size);
154 Seobeo_Handle_Flush(p_cli_handle); 185 Seobeo_Handle_Flush(p_cli_handle);
155 186
284 perror("Dowa_Cache_Folder"); 315 perror("Dowa_Cache_Folder");
285 return -1; 316 return -1;
286 } 317 }
287 318
288 Seobeo_PHandle p_server_handle = 319 Seobeo_PHandle p_server_handle =
289 Seobeo_Stream_Handle_Create(NULL, port); 320 Seobeo_Stream_Handle_Server_Create(NULL, port);
290 if (p_server_handle->socket < 0) return 1; 321 if (p_server_handle->socket < 0) return 1;
322
291 printf("Listening on port %s\n", port); 323 printf("Listening on port %s\n", port);
292 324
293 // Fork‐based fallback 325 // Fork‐based fallback
294 if (mode == SEOBEO_MODE_FORK) 326 if (mode == SEOBEO_MODE_FORK)
295 { 327 {
328 printf("FORK MODE\n");
296 struct sigaction sa; 329 struct sigaction sa;
297 sa.sa_handler = SigchildHandler; 330 sa.sa_handler = SigchildHandler;
298 sigemptyset(&sa.sa_mask); 331 sigemptyset(&sa.sa_mask);
299 sa.sa_flags = SA_RESTART; 332 sa.sa_flags = SA_RESTART;
300 sigaction(SIGCHLD, &sa, NULL); 333 sigaction(SIGCHLD, &sa, NULL);
314 } 347 }
315 } 348 }
316 349
317 if (mode == SEOBEO_MODE_EDGE) 350 if (mode == SEOBEO_MODE_EDGE)
318 { 351 {
352 printf("EDGE MODE\n");
319 Seobeo_Web_Edge(p_server_handle, thread_count, p_html_cache); 353 Seobeo_Web_Edge(p_server_handle, thread_count, p_html_cache);
320 } 354 }
321 355
322 return -1; 356 return -1;
323 } 357 }
325 359
326 int Seobeo_Web_ClientGet(const char *host, 360 int Seobeo_Web_ClientGet(const char *host,
327 const char *port, 361 const char *port,
328 const char *path) 362 const char *path)
329 { 363 {
330 Seobeo_PHandle h = Seobeo_Stream_Handle_Create(host, port); 364 Seobeo_PHandle h = Seobeo_Stream_Handle_Client_Create(host, port, TRUE);
331 if (!h || h->socket < 0) 365 if (!h || h->socket < 0)
332 { 366 {
333 if (h) Seobeo_Handle_Destroy(h); 367 if (h)
368 Seobeo_Handle_Destroy(h);
334 return -1; 369 return -1;
335 } 370 }
336 371
337 Dowa_PArena p_request_arena = Dowa_Arena_Create(1 * 1024 * 1024); 372 Dowa_PArena p_request_arena = Dowa_Arena_Create(1 * 1024 * 1024);
338 if (!p_request_arena) 373 if (!p_request_arena) { perror("Dowa_Arena_Create"); return -1; }
339 { 374
340 perror("Dowa_Arena_Create");
341 return -1;
342 }
343 void *p_request_header = Dowa_Arena_Allocate(p_request_arena, 4096); 375 void *p_request_header = Dowa_Arena_Allocate(p_request_arena, 4096);
344 if (!p_request_header) 376 if (!p_request_header) { perror("Dowa_Arena_Allocate"); return -1; }
345 {
346 perror("Dowa_Arena_Allocate");
347 return -1;
348 }
349 377
350 int request_len = Seobeo_Web_GenerateRequestHeader(p_request_header, host, path); 378 int request_len = Seobeo_Web_GenerateRequestHeader(p_request_header, host, path);
351 printf("request: %s\n", (char *)p_request_header); 379 // DEBUG
380 // printf("request: %s\n", (char *)p_request_header);
352 Seobeo_Handle_Queue(h, (uint8 *)p_request_header, (uint32)request_len); 381 Seobeo_Handle_Queue(h, (uint8 *)p_request_header, (uint32)request_len);
353
354 if (Seobeo_Handle_Flush(h) < 0) 382 if (Seobeo_Handle_Flush(h) < 0)
355 { 383 {
356 perror("Seobeo_Handle_Flush"); 384 perror("Seobeo_Handle_Flush");
357 Seobeo_Handle_Destroy(h); 385 Seobeo_Handle_Destroy(h);
358 return -1; 386 return -1;
359 } 387 }
360 388
389 // Response
361 size_t cap = 1024*8, used = 0; 390 size_t cap = 1024*8, used = 0;
362 char *p_request_body = Dowa_Arena_Allocate(p_request_arena, cap); 391 char *p_request_body = Dowa_Arena_Allocate(p_request_arena, cap);
363 if (!p_request_body) { Seobeo_Handle_Destroy(h); return -1; } 392 if (!p_request_body) { Seobeo_Handle_Destroy(h); return -1; }
364 393
365 while (1) { 394 while (1)
395 {
366 int n = Seobeo_Handle_Read(h); 396 int n = Seobeo_Handle_Read(h);
397 printf("Size: %d\n", n);
367 if (n > 0) 398 if (n > 0)
368 { 399 {
400 // TODO: Maybe directly use arena inside of the struct? idk if that is useful or not...
369 memcpy(p_request_body + used, h->read_buffer, h->read_buffer_len); 401 memcpy(p_request_body + used, h->read_buffer, h->read_buffer_len);
370 used += h->read_buffer_len; 402 used += h->read_buffer_len;
371 Seobeo_Handle_Consume(h, (uint32)h->read_buffer_len); 403 Seobeo_Handle_Consume(h, (uint32)h->read_buffer_len);
372 } 404 }else if (n == 0)
373 else if (n == 0) 405 {
374 { 406 // Wait
375 // non-blocking mode and no data right now → keep looping or break?
376 // For a simple blocking client, you could block instead:
377 continue; 407 continue;
378 } 408 }else if (n == -2)
379 else if (n == -2) 409 {
380 { 410 // Debug
381 // peer closed; we’ve got everything 411 // peer closed; we’ve got everything
412 printf("\n\nCLOSED\n\n");
382 break; 413 break;
383 } 414 }else
384 else
385 { 415 {
386 Dowa_Arena_Free(p_request_arena); 416 Dowa_Arena_Free(p_request_arena);
387 Seobeo_Handle_Destroy(h); 417 Seobeo_Handle_Destroy(h);
388 return -1; 418 return -1;
389 } 419 }
390 } 420 }
391 421
392 printf("%s\n\n", p_request_body); 422 printf("%s", p_request_body);
393 Dowa_Arena_Free(p_request_arena); 423 Dowa_Arena_Free(p_request_arena);
394 Seobeo_Handle_Destroy(h); 424 Seobeo_Handle_Destroy(h);
395 return 0; 425 return 0;
396 } 426 }