WebSocket request/response header dance. Feels like the loop is getting close to closed, but I want to refactor everything.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4692 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2023-12-24 17:43:33 +00:00
parent 196ab66e14
commit 1621f1753a
5 changed files with 90 additions and 13 deletions

View File

@ -39,6 +39,7 @@ typedef struct _tf_http_connection_t
int headers_length;
bool headers_done;
int flags;
tf_http_callback_t* callback;
void* user_data;
@ -51,6 +52,7 @@ typedef struct _tf_http_connection_t
typedef struct _tf_http_handler_t
{
const char* pattern;
int flags;
tf_http_callback_t* callback;
void* user_data;
} tf_http_handler_t;
@ -70,6 +72,7 @@ typedef struct _tf_http_t
uv_loop_t* loop;
} tf_http_t;
static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name);
static void _http_connection_destroy(tf_http_connection_t* connection);
static const char* _http_status_text(int status);
@ -96,13 +99,14 @@ void _http_allocate_buffer(uv_handle_t* handle, size_t suggestedSize, uv_buf_t*
}
}
bool _http_find_handler(tf_http_t* http, const char* path, tf_http_callback_t** out_callback, void** out_user_data)
bool _http_find_handler(tf_http_t* http, const char* path, int flags, tf_http_callback_t** out_callback, void** out_user_data)
{
for (int i = 0; i < http->handlers_count; i++)
{
if (!http->handlers[i].pattern ||
if (http->handlers[i].flags == flags &&
(!http->handlers[i].pattern ||
strcmp(path, http->handlers[i].pattern) == 0 ||
(strncmp(path, http->handlers[i].pattern, strlen(http->handlers[i].pattern)) == 0 && path[strlen(http->handlers[i].pattern)] == '/'))
(strncmp(path, http->handlers[i].pattern, strlen(http->handlers[i].pattern)) == 0 && path[strlen(http->handlers[i].pattern)] == '/')))
{
*out_callback = http->handlers[i].callback;
*out_user_data = http->handlers[i].user_data;
@ -182,6 +186,7 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
.phase = k_http_callback_phase_headers_received,
.method = connection->method,
.path = connection->path,
.flags = connection->flags,
.query = connection->query,
.body = connection->body,
.content_length = connection->content_length,
@ -189,6 +194,7 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
.headers_count = connection->headers_length,
.user_data = connection->user_data,
};
tf_http_request_ref(request);
connection->callback(request);
tf_http_request_release(request);
@ -260,7 +266,9 @@ static void _http_on_read(uv_stream_t* stream, ssize_t read_size, const uv_buf_t
connection->body = tf_malloc(connection->content_length);
}
if (!_http_find_handler(connection->http, connection->path, &connection->callback, &connection->user_data) || !connection->callback)
int flags = _http_connection_get_header(connection, "upgrade") ? k_tf_http_handler_flag_websocket : 0;
connection->flags = flags;
if (!_http_find_handler(connection->http, connection->path, flags, &connection->callback, &connection->user_data) || !connection->callback)
{
connection->callback = _http_builtin_404_handler;
}
@ -365,12 +373,13 @@ void tf_http_listen(tf_http_t* http, int port)
}
}
void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, void* user_data)
void tf_http_add_handler(tf_http_t* http, const char* pattern, int flags, tf_http_callback_t* callback, void* user_data)
{
http->handlers = tf_realloc(http->handlers, sizeof(tf_http_handler_t) * (http->handlers_count + 1));
http->handlers[http->handlers_count++] = (tf_http_handler_t)
{
.pattern = tf_strdup(pattern),
.flags = flags,
.callback = callback,
.user_data = user_data,
};
@ -451,7 +460,7 @@ void tf_http_respond(tf_http_request_t* request, int status, const char** header
char content_length_buffer[32] = { 0 };
int content_length_buffer_length = 0;
if (!sent_content_length)
if (!sent_content_length && status != 101)
{
content_length_buffer_length = snprintf(content_length_buffer, sizeof(content_length_buffer), "Content-Length: %zd\r\n", content_length);
headers_length += content_length_buffer_length;
@ -513,3 +522,20 @@ void tf_http_request_release(tf_http_request_t* request)
tf_free(request);
}
}
static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name)
{
for (int i = 0; i < connection->headers_length; i++)
{
if (strcasecmp(connection->headers[i].name, name) == 0)
{
return connection->headers[i].value;
}
}
return NULL;
}
const char* tf_http_request_get_header(tf_http_request_t* request, const char* name)
{
return _http_connection_get_header(request->connection, name);
}