emme coverage


Directory: src/
File: src/http2_response.c
Date: 2026-05-14 14:35:13
Exec Total Coverage
Lines: 58 62 93.5%
Functions: 8 8 100.0%
Branches: 25 44 56.8%

Line Branch Exec Source
1 #include "http2_response.h"
2 #include <string.h>
3 #include <stdio.h>
4 #include "metrics.h"
5
6 5 void h2_response_init(Http2Response *resp)
7 {
8 5 memset(resp, 0, sizeof(Http2Response));
9 5 resp->status_code = 200;
10 5 strcpy(resp->status_text, "OK");
11 5 strcpy(resp->content_type, "text/html");
12 5 }
13
14 5 void h2_response_set_status(Http2Response *resp, int status_code, const char *status_text)
15 {
16 5 resp->status_code = status_code;
17
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 snprintf(resp->status_text, sizeof(resp->status_text), "%s", status_text ? status_text : "OK");
18 5 snprintf(resp->status_code_str, sizeof(resp->status_code_str), "%d", status_code);
19 5 }
20
21 22 void h2_response_add_header(Http2Response *resp, const char *name, const char *value)
22 {
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (resp->num_headers >= 16)
24 return;
25
26 22 resp->headers[resp->num_headers] = MAKE_NV(name, value);
27 22 resp->num_headers++;
28 }
29
30 4 void h2_response_set_body(Http2Response *resp, const char *body, size_t len)
31 {
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (len >= sizeof(resp->body))
33 len = sizeof(resp->body) - 1;
34
35 4 memcpy(resp->body, body, len);
36 4 resp->body[len] = '\0';
37 4 resp->body_len = len;
38 4 }
39
40 1 void h2_response_set_body_len(Http2Response *resp, size_t len)
41 {
42 1 resp->body_len = len;
43 1 }
44
45 4 void h2_response_set_content_type(Http2Response *resp, const char *content_type)
46 {
47 4 snprintf(resp->content_type, sizeof(resp->content_type), "%s", content_type);
48 4 }
49
50 1 void h2_response_finalize(Http2Response *resp)
51 {
52 1 snprintf(resp->content_length_str, sizeof(resp->content_length_str), "%zu", resp->body_len);
53 1 }
54
55 5 void h2_response_add_security_headers(Http2Response *resp, SecurityHeadersConfig *config, CORSConfig *cors)
56 {
57 5 int sec_headers_added = 0;
58 5 int cors_headers_added = 0;
59
60
4/6
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
5 if (!resp || !config || !config->enabled)
61 2 return;
62
63
3/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
21 for (int i = 0; i < config->header_count && resp->num_headers < 16; i++) {
64 18 const SecurityHeader *header = &config->headers[i];
65 18 h2_response_add_header(resp, header->name, header->value);
66 18 sec_headers_added++;
67 }
68
69
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 if (cors && cors->enabled) {
70
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (cors->allow_origin[0] != '\0' && resp->num_headers < 16) {
71 1 h2_response_add_header(resp, "Access-Control-Allow-Origin", cors->allow_origin);
72 1 cors_headers_added++;
73 }
74
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (cors->allow_methods[0] != '\0' && resp->num_headers < 16) {
75 1 h2_response_add_header(resp, "Access-Control-Allow-Methods", cors->allow_methods);
76 1 cors_headers_added++;
77 }
78
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (cors->allow_headers[0] != '\0' && resp->num_headers < 16) {
79 1 h2_response_add_header(resp, "Access-Control-Allow-Headers", cors->allow_headers);
80 1 cors_headers_added++;
81 }
82
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if (cors->allow_credentials && resp->num_headers < 16) {
83 h2_response_add_header(resp, "Access-Control-Allow-Credentials", "true");
84 cors_headers_added++;
85 }
86
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (cors->max_age_seconds > 0 && resp->num_headers < 16) {
87 char max_age_str[32];
88 1 snprintf(max_age_str, sizeof(max_age_str), "%d", cors->max_age_seconds);
89 1 h2_response_add_header(resp, "Access-Control-Max-Age", max_age_str);
90 1 cors_headers_added++;
91 }
92 }
93
94
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (sec_headers_added > 0) {
95 3 metrics_increment_security_headers_sent();
96 }
97
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (cors_headers_added > 0) {
98 1 metrics_increment_cors_headers_sent();
99 }
100 }
101