comparison seobeo/tests/seobeo_http_content_length_test.c @ 226:3fa4bf481f42

[merge] Merge hg-web into default
author MrJuneJune <me@mrjunejune.com>
date Sun, 02 Aug 2026 14:42:01 -0700
parents ce7f4400c2de
children
comparison
equal deleted inserted replaced
220:eb8b4230fdb9 226:3fa4bf481f42
1 #include "seobeo/seobeo.h"
2
3 #include <arpa/inet.h>
4 #include <pthread.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <time.h>
8
9 typedef struct {
10 int listener;
11 } Content_Length_Server;
12
13 static int64_t monotonic_milliseconds(void)
14 {
15 struct timespec now;
16 clock_gettime(CLOCK_MONOTONIC, &now);
17 return (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000;
18 }
19
20 static void *serve_lowercase_content_length(void *argument)
21 {
22 Content_Length_Server *server = argument;
23 int client = accept(server->listener, NULL, NULL);
24 if (client >= 0) {
25 char request[1024];
26 (void)read(client, request, sizeof(request));
27 const char response[] =
28 "HTTP/1.1 200 OK\r\n"
29 "content-length: 4\r\n"
30 "Connection: keep-alive\r\n"
31 "\r\n"
32 "done";
33 (void)write(client, response, sizeof(response) - 1);
34 usleep(500000);
35 close(client);
36 }
37 return NULL;
38 }
39
40 int main(void)
41 {
42 int listener = socket(AF_INET, SOCK_STREAM, 0);
43 if (listener < 0)
44 return 1;
45
46 struct sockaddr_in address = {
47 .sin_family = AF_INET,
48 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
49 .sin_port = 0,
50 };
51 if (bind(listener, (struct sockaddr *)&address, sizeof(address)) != 0 ||
52 listen(listener, 1) != 0) {
53 close(listener);
54 return 1;
55 }
56
57 socklen_t address_length = sizeof(address);
58 if (getsockname(listener, (struct sockaddr *)&address, &address_length) != 0) {
59 close(listener);
60 return 1;
61 }
62
63 Content_Length_Server server = {.listener = listener};
64 pthread_t thread;
65 if (pthread_create(&thread, NULL, serve_lowercase_content_length, &server) != 0) {
66 close(listener);
67 return 1;
68 }
69
70 char url[128];
71 snprintf(url, sizeof(url), "http://127.0.0.1:%u/", ntohs(address.sin_port));
72 Seobeo_Client_Request *request = Seobeo_Client_Request_Create(url);
73 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, 1000);
74 int64_t started = monotonic_milliseconds();
75 Seobeo_Client_Response *response = Seobeo_Client_Request_Execute(request);
76 int64_t elapsed = monotonic_milliseconds() - started;
77
78 int failed = !response ||
79 response->body_length != 4 ||
80 memcmp(response->body, "done", 4) != 0 ||
81 elapsed > 300;
82 if (failed)
83 fprintf(stderr, "Case-insensitive Content-Length was not honored (%lldms)\n",
84 (long long)elapsed);
85
86 Seobeo_Client_Response_Destroy(response);
87 Seobeo_Client_Request_Destroy(request);
88 pthread_join(thread, NULL);
89 close(listener);
90 return failed;
91 }