Add Cookie headers when starting an HTTP request

This commit is contained in:
2025-11-23 19:22:38 +01:00
parent fc49b55225
commit e5358d883b
2 changed files with 108 additions and 11 deletions
+80 -2
View File
@@ -143,6 +143,67 @@ int http_client_get_builder(HTTP_Client *client,
return 0;
}
// TODO: test this function
static bool is_subdomain(HTTP_String domain, HTTP_String subdomain)
{
if (http_streq(domain, subdomain))
return true; // Exact match
if (domain.len > subdomain.len)
return false;
HTTP_String subdomain_suffix = {
subdomain.ptr + subdomain.len - domain.len,
entry.domain.len
};
if (subdomain_suffix.ptr[-1] != '.' || !http_streq(domain, subdomain_suffix))
return false;
return true;
}
// TODO: test this function
static bool is_subpath(HTTP_String path, HTTP_String subpath)
{
if (path.len > subpath.len)
return false;
if (subpath.len != path.len && subpath.ptr[path.len] != '/')
return false;
subpath.len = path.len;
return http_streq(path, subpath);
}
static bool should_send_cookie(HTTP_CookieJarEntry entry, HTTP_URL url)
{
if (entry.exact_domain) {
// Cookie domain and URL domain must match exactly
if (!http_streq(entry.domain, url.authority.host.text))
return false;
} else {
// The URL's domain must match or be a subdomain of the cookie's domain
if (!is_subdomain(entry.domain, url.authority.host.text))
return false;
}
if (entry.exact_path) {
// Cookie path and URL path must match exactly
if (!http_streq(entry.path, url.path))
return false;
} else {
if (!is_subpath(entry.path, url.path))
return false;
}
if (entry.secure) {
if (!http_streq(url.scheme, HTTP_STR("https"))
return false; // Cookie was marked as secure but the target URL is not HTTPS
}
return true;
}
void http_request_builder_url(HTTP_RequestBuilder builder,
HTTP_Method method, HTTP_String url)
{
@@ -174,7 +235,6 @@ void http_request_builder_url(HTTP_RequestBuilder builder,
case HTTP_METHOD_OPTIONS: method_str = "OPTIONS"; break;
case HTTP_METHOD_TRACE: method_str = "TRACE"; break;
case HTTP_METHOD_PATCH: method_str = "PATCH"; break;
default: return;
}
// Build request line: METHOD path HTTP/1.1\r\n
@@ -192,8 +252,22 @@ void http_request_builder_url(HTTP_RequestBuilder builder,
}
byte_queue_write(&conn->output, "\r\n", 2);
// TODO: Find all entries from the cookie jar that should
// Find all entries from the cookie jar that should
// be sent to this server and append headers for them
HTTP_CookieJar *cookie_jar = &conn->client->cookie_jar;
for (int i = 0; i < cookie_jar->count; i++) {
HTTP_CookieJarEntry entry = cookie_jar->items[i];
if (should_send_cookie(entry, parsed_url)) {
// TODO: Adding one header per cookie may cause the number of
// headers to increase significantly. Should probably group
// 3-4 cookies in the same headers.
byte_queue_write(&conn->output, HTTP_STR("Cookie: "));
byte_queue_write(&conn->output, entry.name);
byte_queue_write(&conn->output, HTTP_STR("="));
byte_queue_write(&conn->output, entry.value);
byte_queue_write(&conn->output, HTTP_STR("\r\n"));
}
}
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
}
@@ -324,16 +398,20 @@ static void save_cookies(HTTP_CookieJar *cookie_jar, HTTP_Header *headers, int n
if (parsed.have_domain) {
// TODO: Check that the server can set a cookie for this domain
entry.exact_domain = false;
entry.domain = parsed.domain;
} else {
// TODO: Set the domain to the specific one used for this interaction
entry.exact_domain = true;
entry.domain = xxx;
}
if (parsed.have_path) {
antry.exact_path = false;
entry.path = parsed.path;
} else {
// TODO: Set the path to the current endpoint minus one level
entry.exact_path = true;
entry.path = xxx;
}
+19
View File
@@ -12,11 +12,30 @@
#endif
typedef struct {
// Cookie name and value
HTTP_String name;
HTTP_String value;
// If the "exact_domain" is true, the cookie
// can only be sent to the exact domain referred
// to by "domain" (which is never empty). If
// "exact_domain" is false, then the cookie is
// compatible with subdomains.
bool exact_domain;
HTTP_String domain;
// If "exact_path" is set, the cookie is only
// compatible with requests to paths that match
// "path" exactly. If "exact_path" is not set,
// then any path that starts with "path" is
// compatible with the cookie.
bool exact_path;
HTTP_String path;
// This cookie can only be sent over HTTPS
bool secure;
} HTTP_CookieJarEntry;
typedef struct {