Mercurial
comparison seobeo/tests/seobeo_http_framing_test.c @ 221:ce7f4400c2de hg-web
[hg-web] Harden forge and add changeset UI
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sun, 02 Aug 2026 09:01:24 -0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 219:8c9bb0b0759e | 221:ce7f4400c2de |
|---|---|
| 1 #include "seobeo/seobeo.h" | |
| 2 | |
| 3 #include <arpa/inet.h> | |
| 4 #include <pthread.h> | |
| 5 #include <stdio.h> | |
| 6 #include <string.h> | |
| 7 | |
| 8 typedef struct { | |
| 9 int listener; | |
| 10 } Framing_Server; | |
| 11 | |
| 12 static void *serve_close_delimited_response(void *argument) | |
| 13 { | |
| 14 Framing_Server *server = argument; | |
| 15 int client = accept(server->listener, NULL, NULL); | |
| 16 if (client >= 0) { | |
| 17 char request[1024]; | |
| 18 (void)read(client, request, sizeof(request)); | |
| 19 const char response[] = | |
| 20 "HTTP/1.1 200 OK\r\n" | |
| 21 "Content-Type: text/plain\r\n" | |
| 22 "Connection: close\r\n" | |
| 23 "\r\n" | |
| 24 "buffered-body"; | |
| 25 (void)write(client, response, sizeof(response) - 1); | |
| 26 close(client); | |
| 27 } | |
| 28 return NULL; | |
| 29 } | |
| 30 | |
| 31 int main(void) | |
| 32 { | |
| 33 int listener = socket(AF_INET, SOCK_STREAM, 0); | |
| 34 if (listener < 0) | |
| 35 return 1; | |
| 36 | |
| 37 struct sockaddr_in address = { | |
| 38 .sin_family = AF_INET, | |
| 39 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), | |
| 40 .sin_port = 0, | |
| 41 }; | |
| 42 if (bind(listener, (struct sockaddr *)&address, sizeof(address)) != 0 || | |
| 43 listen(listener, 1) != 0) { | |
| 44 close(listener); | |
| 45 return 1; | |
| 46 } | |
| 47 | |
| 48 socklen_t address_length = sizeof(address); | |
| 49 if (getsockname(listener, (struct sockaddr *)&address, &address_length) != 0) { | |
| 50 close(listener); | |
| 51 return 1; | |
| 52 } | |
| 53 | |
| 54 Framing_Server server = {.listener = listener}; | |
| 55 pthread_t thread; | |
| 56 if (pthread_create(&thread, NULL, serve_close_delimited_response, &server) != 0) { | |
| 57 close(listener); | |
| 58 return 1; | |
| 59 } | |
| 60 | |
| 61 char url[128]; | |
| 62 snprintf(url, sizeof(url), "http://127.0.0.1:%u/", ntohs(address.sin_port)); | |
| 63 Seobeo_Client_Request *request = Seobeo_Client_Request_Create(url); | |
| 64 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, 1000); | |
| 65 Seobeo_Client_Response *response = Seobeo_Client_Request_Execute(request); | |
| 66 | |
| 67 int failed = !response || | |
| 68 response->status_code != 200 || | |
| 69 response->body_length != strlen("buffered-body") || | |
| 70 memcmp(response->body, "buffered-body", strlen("buffered-body")) != 0; | |
| 71 if (failed) | |
| 72 fprintf(stderr, "Close-delimited response body was not preserved\n"); | |
| 73 | |
| 74 Seobeo_Client_Response_Destroy(response); | |
| 75 Seobeo_Client_Request_Destroy(request); | |
| 76 pthread_join(thread, NULL); | |
| 77 close(listener); | |
| 78 return failed; | |
| 79 } |