forked from cory/tildefriends
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:
38
src/http.c
38
src/http.c
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user