Add HTTP_CookieJar object to HTTP_Client
This commit is contained in:
@@ -21,6 +21,8 @@ int http_client_init(HTTP_Client *client)
|
|||||||
client->input_buffer_limit = 1<<20;
|
client->input_buffer_limit = 1<<20;
|
||||||
client->output_buffer_limit = 1<<20;
|
client->output_buffer_limit = 1<<20;
|
||||||
|
|
||||||
|
client->cookie_jar.count = 0;
|
||||||
|
|
||||||
client->num_conns = 0;
|
client->num_conns = 0;
|
||||||
for (int i = 0; i < HTTP_CLIENT_CAPACITY; i++) {
|
for (int i = 0; i < HTTP_CLIENT_CAPACITY; i++) {
|
||||||
client->conns[i].state = HTTP_CLIENT_CONN_FREE;
|
client->conns[i].state = HTTP_CLIENT_CONN_FREE;
|
||||||
@@ -40,6 +42,9 @@ void http_client_free(HTTP_Client *client)
|
|||||||
{
|
{
|
||||||
socket_manager_free(&client->sockets);
|
socket_manager_free(&client->sockets);
|
||||||
|
|
||||||
|
for (int i = 0; i < cookie_jar->count; i++)
|
||||||
|
free(client->cookie_jar.items[i].name.ptr);
|
||||||
|
|
||||||
for (int i = 0, j = 0; j < client->num_conns; i++) {
|
for (int i = 0, j = 0; j < client->num_conns; i++) {
|
||||||
HTTP_ClientConn *conn = &client->conns[i];
|
HTTP_ClientConn *conn = &client->conns[i];
|
||||||
if (conn->state == HTTP_CLIENT_CONN_FREE)
|
if (conn->state == HTTP_CLIENT_CONN_FREE)
|
||||||
@@ -187,6 +192,9 @@ void http_request_builder_url(HTTP_RequestBuilder builder,
|
|||||||
}
|
}
|
||||||
byte_queue_write(&conn->output, "\r\n", 2);
|
byte_queue_write(&conn->output, "\r\n", 2);
|
||||||
|
|
||||||
|
// TODO: Find all entries from the cookie jar that should
|
||||||
|
// be sent to this server and append headers for them
|
||||||
|
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,6 +306,65 @@ int http_request_builder_send(HTTP_RequestBuilder builder)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void save_cookies(HTTP_CookieJar *cookie_jar, HTTP_Header *headers, int num_headers)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < num_headers; i++) {
|
||||||
|
if (http_streqcase(headers[i].name, HTTP_STR("Set-Cookie"))) {
|
||||||
|
|
||||||
|
HTTP_SetCookie parsed;
|
||||||
|
if (http_parse_set_cookie(headers[i].value, &parsed) < 0)
|
||||||
|
continue; // Ignore invalid Set-Cookie headers
|
||||||
|
|
||||||
|
if (cookie_jar->count == HTTP_COOKIE_JAR_CAPACITY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
HTTP_CookieJarEntry entry;
|
||||||
|
entry.name = parsed.name;
|
||||||
|
entry.value = parsed.value;
|
||||||
|
|
||||||
|
if (parsed.have_domain) {
|
||||||
|
// TODO: Check that the server can set a cookie for this domain
|
||||||
|
entry.domain = parsed.domain;
|
||||||
|
} else {
|
||||||
|
// TODO: Set the domain to the specific one used for this interaction
|
||||||
|
entry.domain = xxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.have_path) {
|
||||||
|
entry.path = parsed.path;
|
||||||
|
} else {
|
||||||
|
// TODO: Set the path to the current endpoint minus one level
|
||||||
|
entry.path = xxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.secure = parsed.secure;
|
||||||
|
|
||||||
|
// Now copy all fields
|
||||||
|
char *p = malloc(entry.name.len + entry.value.len + entry.domain.len + entry.path.len);
|
||||||
|
if (p == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
memcpy(p, entry.name.ptr, entry.name.len);
|
||||||
|
entry.name.ptr = p;
|
||||||
|
p += entry.name.len;
|
||||||
|
|
||||||
|
memcpy(p, entry.value.ptr, entry.value.len);
|
||||||
|
entry.value.ptr = p;
|
||||||
|
p += entry.value.len;
|
||||||
|
|
||||||
|
memcpy(p, entry.domain.ptr, entry.domain.len);
|
||||||
|
entry.domain.ptr = p;
|
||||||
|
p += entry.domain.len;
|
||||||
|
|
||||||
|
memcpy(p, entry.path.ptr, entry.path.len);
|
||||||
|
entry.path.ptr = p;
|
||||||
|
p += entry.path.len;
|
||||||
|
|
||||||
|
cookie_jar->items[cookie_jar->count++] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Look at the input buffer to see if a complete response
|
// Look at the input buffer to see if a complete response
|
||||||
// was buffered. If it was, change the connection's status
|
// was buffered. If it was, change the connection's status
|
||||||
// to COMPLETE and push it to the ready queue.
|
// to COMPLETE and push it to the ready queue.
|
||||||
@@ -330,6 +397,8 @@ check_response_buffer(HTTP_Client *client, HTTP_ClientConn *conn)
|
|||||||
conn->state = HTTP_CLIENT_CONN_COMPLETE;
|
conn->state = HTTP_CLIENT_CONN_COMPLETE;
|
||||||
conn->response.context = conn;
|
conn->response.context = conn;
|
||||||
|
|
||||||
|
save_cookies(&client->cookie_jar, conn->response.headers, conn->response.num_headers);
|
||||||
|
|
||||||
// Push to the ready queue
|
// Push to the ready queue
|
||||||
assert(client->num_ready < HTTP_CLIENT_CAPACITY);
|
assert(client->num_ready < HTTP_CLIENT_CAPACITY);
|
||||||
int tail = (client->ready_head + client->num_ready) % HTTP_CLIENT_CAPACITY;
|
int tail = (client->ready_head + client->num_ready) % HTTP_CLIENT_CAPACITY;
|
||||||
|
|||||||
@@ -5,6 +5,25 @@
|
|||||||
#define HTTP_CLIENT_CAPACITY (1<<7)
|
#define HTTP_CLIENT_CAPACITY (1<<7)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HTTP_COOKIE_JAR_CAPACITY
|
||||||
|
// Maximum number of cookies that can be associated to a
|
||||||
|
// single client.
|
||||||
|
#define HTTP_COOKIE_JAR_CAPACITY 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HTTP_String name;
|
||||||
|
HTTP_String value;
|
||||||
|
HTTP_String domain;
|
||||||
|
HTTP_String path;
|
||||||
|
bool secure;
|
||||||
|
} HTTP_CookieJarEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int count;
|
||||||
|
HTTP_CookieJarEntry items[HTTP_COOKIE_JAR_CAPACITY];
|
||||||
|
} HTTP_CookieJar;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HTTP_CLIENT_CONN_FREE,
|
HTTP_CLIENT_CONN_FREE,
|
||||||
HTTP_CLIENT_CONN_WAIT_LINE,
|
HTTP_CLIENT_CONN_WAIT_LINE,
|
||||||
@@ -54,6 +73,9 @@ struct HTTP_Client {
|
|||||||
uint32_t input_buffer_limit;
|
uint32_t input_buffer_limit;
|
||||||
uint32_t output_buffer_limit;
|
uint32_t output_buffer_limit;
|
||||||
|
|
||||||
|
// List of cookies created during this session
|
||||||
|
HTTP_CookieJar cookie_jar;
|
||||||
|
|
||||||
// Array of connections. The counter contains the
|
// Array of connections. The counter contains the
|
||||||
// number of structs such that state!=FREE.
|
// number of structs such that state!=FREE.
|
||||||
int num_conns;
|
int num_conns;
|
||||||
|
|||||||
Reference in New Issue
Block a user