forked from cory/tildefriends
Fix some http request lifetime issues, and follow the same lowercase convention for headers.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4690 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
86046e52f0
commit
38ab32dad9
34
src/http.c
34
src/http.c
@ -21,6 +21,8 @@ typedef struct _tf_http_connection_t
|
|||||||
uv_tcp_t tcp;
|
uv_tcp_t tcp;
|
||||||
uv_shutdown_t shutdown;
|
uv_shutdown_t shutdown;
|
||||||
|
|
||||||
|
int ref_count;
|
||||||
|
|
||||||
const char* method;
|
const char* method;
|
||||||
const char* path;
|
const char* path;
|
||||||
int minor_version;
|
int minor_version;
|
||||||
@ -127,7 +129,7 @@ static void _http_connection_destroy(tf_http_connection_t* connection)
|
|||||||
{
|
{
|
||||||
uv_close((uv_handle_t*)&connection->tcp, _http_connection_on_close);
|
uv_close((uv_handle_t*)&connection->tcp, _http_connection_on_close);
|
||||||
}
|
}
|
||||||
else
|
else if (connection->ref_count == 0)
|
||||||
{
|
{
|
||||||
tf_http_t* http = connection->http;
|
tf_http_t* http = connection->http;
|
||||||
for (int i = 0; i < http->connections_count; i++)
|
for (int i = 0; i < http->connections_count; i++)
|
||||||
@ -182,7 +184,9 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
|
|||||||
.headers_count = connection->headers_length,
|
.headers_count = connection->headers_length,
|
||||||
.user_data = connection->user_data,
|
.user_data = connection->user_data,
|
||||||
};
|
};
|
||||||
|
tf_http_request_ref(request);
|
||||||
connection->callback(request);
|
connection->callback(request);
|
||||||
|
tf_http_request_release(request);
|
||||||
_http_reset_connection(connection);
|
_http_reset_connection(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,6 +211,7 @@ static void _http_on_read(uv_stream_t* stream, ssize_t read_size, const uv_buf_t
|
|||||||
if (parse_result > 0)
|
if (parse_result > 0)
|
||||||
{
|
{
|
||||||
connection->headers_done = true;
|
connection->headers_done = true;
|
||||||
|
connection->headers_length = header_count;
|
||||||
connection->method = method;
|
connection->method = method;
|
||||||
((char*)connection->method)[method_length] = '\0';
|
((char*)connection->method)[method_length] = '\0';
|
||||||
connection->path = path;
|
connection->path = path;
|
||||||
@ -216,6 +221,14 @@ static void _http_on_read(uv_stream_t* stream, ssize_t read_size, const uv_buf_t
|
|||||||
|
|
||||||
for (int i = 0; i < (int)header_count; i++)
|
for (int i = 0; i < (int)header_count; i++)
|
||||||
{
|
{
|
||||||
|
for (size_t j = 0; j < connection->headers[i].name_len; j++)
|
||||||
|
{
|
||||||
|
if (connection->headers[i].name[j] >= 'A' &&
|
||||||
|
connection->headers[i].name[j] <= 'Z')
|
||||||
|
{
|
||||||
|
((char*)connection->headers[i].name)[j] += 'a' - 'A';
|
||||||
|
}
|
||||||
|
}
|
||||||
((char*)connection->headers[i].name)[connection->headers[i].name_len] = '\0';
|
((char*)connection->headers[i].name)[connection->headers[i].name_len] = '\0';
|
||||||
((char*)connection->headers[i].value)[connection->headers[i].value_len] = '\0';
|
((char*)connection->headers[i].value)[connection->headers[i].value_len] = '\0';
|
||||||
if (strcasecmp(connection->headers[i].name, "content-length") == 0)
|
if (strcasecmp(connection->headers[i].name, "content-length") == 0)
|
||||||
@ -464,7 +477,6 @@ void tf_http_respond(tf_http_request_t* request, int status, const char** header
|
|||||||
request->connection->shutdown.data = request->connection;
|
request->connection->shutdown.data = request->connection;
|
||||||
uv_shutdown(&request->connection->shutdown, (uv_stream_t*)&request->connection->tcp, _http_on_shutdown);
|
uv_shutdown(&request->connection->shutdown, (uv_stream_t*)&request->connection->tcp, _http_on_shutdown);
|
||||||
}
|
}
|
||||||
tf_free(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data)
|
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data)
|
||||||
@ -472,3 +484,21 @@ size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data)
|
|||||||
*out_data = request->connection->body;
|
*out_data = request->connection->body;
|
||||||
return request->connection->content_length;
|
return request->connection->content_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tf_http_request_ref(tf_http_request_t* request)
|
||||||
|
{
|
||||||
|
request->ref_count++;
|
||||||
|
request->connection->ref_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tf_http_request_release(tf_http_request_t* request)
|
||||||
|
{
|
||||||
|
if (--request->connection->ref_count == 0)
|
||||||
|
{
|
||||||
|
/* Reset the connection? */
|
||||||
|
}
|
||||||
|
if (--request->ref_count == 0)
|
||||||
|
{
|
||||||
|
tf_free(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ typedef struct _tf_http_request_t
|
|||||||
struct phr_header* headers;
|
struct phr_header* headers;
|
||||||
int headers_count;
|
int headers_count;
|
||||||
void* user_data;
|
void* user_data;
|
||||||
|
int ref_count;
|
||||||
} tf_http_request_t;
|
} tf_http_request_t;
|
||||||
|
|
||||||
typedef void (tf_http_callback_t)(tf_http_request_t* request);
|
typedef void (tf_http_callback_t)(tf_http_request_t* request);
|
||||||
@ -31,3 +32,6 @@ void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_
|
|||||||
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
|
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
|
||||||
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
|
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
|
||||||
void tf_http_destroy(tf_http_t* http);
|
void tf_http_destroy(tf_http_t* http);
|
||||||
|
|
||||||
|
void tf_http_request_ref(tf_http_request_t* request);
|
||||||
|
void tf_http_request_release(tf_http_request_t* request);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static JSClassID _httpd_class_id;
|
static JSClassID _httpd_class_id;
|
||||||
static JSClassID _httpd_response_class_id;
|
static JSClassID _httpd_request_class_id;
|
||||||
|
|
||||||
typedef struct _http_handler_data_t
|
typedef struct _http_handler_data_t
|
||||||
{
|
{
|
||||||
@ -32,7 +32,7 @@ static JSValue _httpd_response_write_head(JSContext* context, JSValueConst this_
|
|||||||
|
|
||||||
static JSValue _httpd_response_end(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
static JSValue _httpd_response_end(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
{
|
{
|
||||||
tf_http_request_t* request = JS_GetOpaque(this_val, _httpd_response_class_id);
|
tf_http_request_t* request = JS_GetOpaque(this_val, _httpd_request_class_id);
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
const void* data = NULL;
|
const void* data = NULL;
|
||||||
JSValue buffer;
|
JSValue buffer;
|
||||||
@ -104,17 +104,18 @@ static void _httpd_callback(tf_http_request_t* request)
|
|||||||
JSValue request_object = JS_NewObject(context);
|
JSValue request_object = JS_NewObject(context);
|
||||||
JS_SetPropertyStr(context, request_object, "uri", JS_NewString(context, request->path));
|
JS_SetPropertyStr(context, request_object, "uri", JS_NewString(context, request->path));
|
||||||
JSValue headers = JS_NewObject(context);
|
JSValue headers = JS_NewObject(context);
|
||||||
JS_SetPropertyStr(context, request_object, "headers", headers);
|
|
||||||
for (int i = 0; i < request->headers_count; i++)
|
for (int i = 0; i < request->headers_count; i++)
|
||||||
{
|
{
|
||||||
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
||||||
}
|
}
|
||||||
|
JS_SetPropertyStr(context, request_object, "headers", headers);
|
||||||
|
|
||||||
JSValue client = JS_NewObject(context);
|
JSValue client = JS_NewObject(context);
|
||||||
JS_SetPropertyStr(context, client, "tls", JS_FALSE);
|
JS_SetPropertyStr(context, client, "tls", JS_FALSE);
|
||||||
JS_SetPropertyStr(context, request_object, "client", client);
|
JS_SetPropertyStr(context, request_object, "client", client);
|
||||||
|
|
||||||
JSValue response_object = JS_NewObjectClass(context, _httpd_response_class_id);
|
JSValue response_object = JS_NewObjectClass(context, _httpd_request_class_id);
|
||||||
|
tf_http_request_ref(request);
|
||||||
JS_SetOpaque(response_object, request);
|
JS_SetOpaque(response_object, request);
|
||||||
JS_SetPropertyStr(context, response_object, "writeHead", JS_NewCFunction(context, _httpd_response_write_head, "writeHead", 2));
|
JS_SetPropertyStr(context, response_object, "writeHead", JS_NewCFunction(context, _httpd_response_write_head, "writeHead", 2));
|
||||||
JS_SetPropertyStr(context, response_object, "end", JS_NewCFunction(context, _httpd_response_end, "end", 1));
|
JS_SetPropertyStr(context, response_object, "end", JS_NewCFunction(context, _httpd_response_end, "end", 1));
|
||||||
@ -161,19 +162,34 @@ void _httpd_finalizer(JSRuntime* runtime, JSValue value)
|
|||||||
tf_http_destroy(http);
|
tf_http_destroy(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _httpd_request_finalizer(JSRuntime* runtime, JSValue value)
|
||||||
|
{
|
||||||
|
tf_http_request_t* request = JS_GetOpaque(value, _httpd_request_class_id);
|
||||||
|
tf_http_request_release(request);
|
||||||
|
}
|
||||||
|
|
||||||
void tf_httpd_register(JSContext* context)
|
void tf_httpd_register(JSContext* context)
|
||||||
{
|
{
|
||||||
JS_NewClassID(&_httpd_class_id);
|
JS_NewClassID(&_httpd_class_id);
|
||||||
JS_NewClassID(&_httpd_response_class_id);
|
JS_NewClassID(&_httpd_request_class_id);
|
||||||
JSClassDef def =
|
JSClassDef httpd_def =
|
||||||
{
|
{
|
||||||
.class_name = "Httpd",
|
.class_name = "Httpd",
|
||||||
.finalizer = &_httpd_finalizer,
|
.finalizer = &_httpd_finalizer,
|
||||||
};
|
};
|
||||||
if (JS_NewClass(JS_GetRuntime(context), _httpd_class_id, &def) != 0)
|
if (JS_NewClass(JS_GetRuntime(context), _httpd_class_id, &httpd_def) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to register Httpd.\n");
|
fprintf(stderr, "Failed to register Httpd.\n");
|
||||||
}
|
}
|
||||||
|
JSClassDef request_def =
|
||||||
|
{
|
||||||
|
.class_name = "Request",
|
||||||
|
.finalizer = &_httpd_request_finalizer,
|
||||||
|
};
|
||||||
|
if (JS_NewClass(JS_GetRuntime(context), _httpd_request_class_id, &request_def) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to register Request.\n");
|
||||||
|
}
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
JSValue httpd = JS_NewObjectClass(context, _httpd_class_id);
|
JSValue httpd = JS_NewObjectClass(context, _httpd_class_id);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user