Add http_get_cookie, http_get_param, http_get_param_i

This commit is contained in:
2025-09-21 10:47:48 +02:00
parent b1021deb15
commit d2fa677ac8
2 changed files with 158 additions and 0 deletions
+153
View File
@@ -1151,3 +1151,156 @@ int http_parse_response(char *src, int len, HTTP_Response *res)
return s.cur; return s.cur;
return ret; return ret;
} }
HTTP_String http_get_cookie(HTTP_Request *req, HTTP_String name)
{
// TODO: best-effort implementation
for (int i = 0; i < req->num_headers; i++) {
if (!http_streqcase(req->headers[i].name, HTTP_STR("Cookie")))
continue;
char *src = req->headers[i].value.ptr;
int len = req->headers[i].value.len;
int cur = 0;
// Cookie: name1=value1; name2=value2; name3=value3
for (;;) {
while (cur < len && src[cur] == ' ')
cur++;
int off = cur;
while (cur < len && src[cur] != '=')
cur++;
HTTP_String cookie_name = { src + off, cur - off };
if (cur == len)
break;
cur++;
off = cur;
while (cur < len && src[cur] != ';')
cur++;
HTTP_String cookie_value = { src + off, cur - off };
if (http_streq(name, cookie_name))
return cookie_value;
if (cur == len)
break;
cur++;
}
}
return HTTP_STR("");
}
HTTP_String http_get_param(HTTP_String body, HTTP_String str, char *mem, int cap)
{
// This is just a best-effort implementation
char *src = body.ptr;
int len = body.len;
int cur = 0;
if (cur < len && src[cur] == '?')
cur++;
while (cur < len) {
HTTP_String name;
{
int off = cur;
while (cur < len && src[cur] != '=' && src[cur] != '&')
cur++;
name = (HTTP_String) { src + off, cur - off };
}
HTTP_String body = HTTP_STR("");
if (cur < len) {
cur++;
if (src[cur-1] == '=') {
int off = cur;
while (cur < len && src[cur] != '&')
cur++;
body = (HTTP_String) { src + off, cur - off };
if (cur < len)
cur++;
}
}
if (http_streq(str, name)) {
bool percent_encoded = false;
for (int i = 0; i < body.len; i++)
if (body.ptr[i] == '+' || body.ptr[i] == '%') {
percent_encoded = true;
break;
}
if (!percent_encoded)
return body;
if (body.len > cap)
return (HTTP_String) { NULL, 0 };
HTTP_String decoded = { mem, 0 };
for (int i = 0; i < body.len; i++) {
char c = body.ptr[i];
if (c == '+')
c = ' ';
else {
if (body.ptr[i] == '%') {
if (body.len - i < 3
|| !is_hex_digit(body.ptr[i+1])
|| !is_hex_digit(body.ptr[i+2]))
return (HTTP_String) { NULL, 0 };
int h = hex_digit_to_int(body.ptr[i+1]);
int l = hex_digit_to_int(body.ptr[i+2]);
c = (h << 4) | l;
i += 2;
}
}
decoded.ptr[decoded.len++] = c;
}
return decoded;
}
}
return HTTP_STR("");
}
static bool is_digit(char c)
{
return c >= '0' && c <= '9';
}
int http_get_param_i(HTTP_String body, HTTP_String str)
{
char buf[128];
HTTP_String out = http_get_param(body, str, buf, SIZEOF(buf));
if (out.len == 0 || !is_digit(out.ptr[0]))
return -1;
int cur = 0;
int res = 0;
do {
int d = out.ptr[cur++] - '0';
if (res > (INT_MAX - d) / 10)
return -1;
res = res * 10 + d;
} while (cur < out.len && is_digit(out.ptr[cur]));
return res;
}
+5
View File
@@ -92,4 +92,9 @@ int http_parse_response (char *src, int len, HTTP_Response *res);
int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name); int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name);
HTTP_String http_get_cookie (HTTP_Request *req, HTTP_String name);
HTTP_String http_get_param (HTTP_String body, HTTP_String str, char *mem, int cap);
int http_get_param_i (HTTP_String body, HTTP_String str);
#endif // PARSE_INCLUDED #endif // PARSE_INCLUDED