forked from cory/tildefriends
Return legit responses for some static files.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4687 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
6ecbfe3de6
commit
7dc8b86ee2
13
src/http.c
13
src/http.c
@ -170,7 +170,8 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d
|
|||||||
|
|
||||||
if (connection->body_length == connection->content_length)
|
if (connection->body_length == connection->content_length)
|
||||||
{
|
{
|
||||||
tf_http_request_t request =
|
tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
|
||||||
|
*request = (tf_http_request_t)
|
||||||
{
|
{
|
||||||
.connection = connection,
|
.connection = connection,
|
||||||
.phase = k_http_callback_phase_headers_received,
|
.phase = k_http_callback_phase_headers_received,
|
||||||
@ -180,7 +181,7 @@ 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,
|
||||||
};
|
};
|
||||||
connection->callback(&request);
|
connection->callback(request);
|
||||||
_http_reset_connection(connection);
|
_http_reset_connection(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,8 +388,15 @@ static const char* _http_status_text(int status)
|
|||||||
{
|
{
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
|
case 101: return "Switching Protocols";
|
||||||
case 200: return "OK";
|
case 200: return "OK";
|
||||||
|
case 303: return "See other";
|
||||||
|
case 304: return "Not Modified";
|
||||||
|
case 400: return "Bad Request";
|
||||||
|
case 401: return "Unauthorized";
|
||||||
|
case 403: return "Forbidden";
|
||||||
case 404: return "File not found";
|
case 404: return "File not found";
|
||||||
|
case 500: return "Internal server error";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,6 +463,7 @@ void tf_http_respond(tf_http_request_t* request, int status, const char** header
|
|||||||
*shutdown_request = (uv_shutdown_t) { .data = request };
|
*shutdown_request = (uv_shutdown_t) { .data = request };
|
||||||
uv_shutdown(shutdown_request, (uv_stream_t*)&request->connection->tcp, _http_on_shutdown);
|
uv_shutdown(shutdown_request, (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)
|
||||||
|
116
src/httpd.js.c
116
src/httpd.js.c
@ -6,7 +6,14 @@
|
|||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
|
|
||||||
|
#include "picohttpparser.h"
|
||||||
|
|
||||||
|
#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(_WIN32)
|
||||||
|
#include <alloca.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static JSClassID _httpd_class_id;
|
static JSClassID _httpd_class_id;
|
||||||
|
static JSClassID _httpd_response_class_id;
|
||||||
|
|
||||||
typedef struct _http_handler_data_t
|
typedef struct _http_handler_data_t
|
||||||
{
|
{
|
||||||
@ -14,14 +21,111 @@ typedef struct _http_handler_data_t
|
|||||||
JSValue callback;
|
JSValue callback;
|
||||||
} http_handler_data_t;
|
} http_handler_data_t;
|
||||||
|
|
||||||
|
static JSValue _httpd_response_write_head(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, this_val, "response_status", JS_DupValue(context, argv[0]));
|
||||||
|
JS_SetPropertyStr(context, this_val, "response_headers", JS_DupValue(context, argv[1]));
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
size_t length = 0;
|
||||||
|
const void* data = NULL;
|
||||||
|
JSValue buffer;
|
||||||
|
if (JS_IsString(argv[0]))
|
||||||
|
{
|
||||||
|
data = JS_ToCStringLen(context, &length, argv[0]);
|
||||||
|
}
|
||||||
|
else if ((data = tf_util_try_get_array_buffer(context, &length, argv[0])) != 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
size_t element_size;
|
||||||
|
buffer = tf_util_try_get_typed_array_buffer(context, argv[0], &offset, &size, &element_size);
|
||||||
|
if (!JS_IsException(buffer))
|
||||||
|
{
|
||||||
|
data = tf_util_try_get_array_buffer(context, &length, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JSValue response_status = JS_GetPropertyStr(context, this_val, "response_status");
|
||||||
|
int status = 0;
|
||||||
|
JS_ToInt32(context, &status, response_status);
|
||||||
|
JS_FreeValue(context, response_status);
|
||||||
|
|
||||||
|
const char** headers = NULL;
|
||||||
|
int headers_length = 0;
|
||||||
|
JSValue response_headers = JS_GetPropertyStr(context, this_val, "response_headers");
|
||||||
|
JSPropertyEnum* ptab;
|
||||||
|
uint32_t plen;
|
||||||
|
JS_GetOwnPropertyNames(context, &ptab, &plen, response_headers, JS_GPN_STRING_MASK);
|
||||||
|
headers = alloca(sizeof(const char*) * plen * 2);
|
||||||
|
headers_length = plen;
|
||||||
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
|
{
|
||||||
|
JSValue key = JS_AtomToString(context, ptab[i].atom);
|
||||||
|
JSPropertyDescriptor desc;
|
||||||
|
JSValue key_value = JS_NULL;
|
||||||
|
if (JS_GetOwnProperty(context, &desc, response_headers, ptab[i].atom) == 1)
|
||||||
|
{
|
||||||
|
key_value = desc.value;
|
||||||
|
JS_FreeValue(context, desc.setter);
|
||||||
|
JS_FreeValue(context, desc.getter);
|
||||||
|
}
|
||||||
|
headers[i * 2 + 0] = JS_ToCString(context, key);
|
||||||
|
headers[i * 2 + 1] = JS_ToCString(context, key_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
tf_http_respond(request, status, headers, headers_length, data, length);
|
||||||
|
|
||||||
|
for (int i = 0; i < headers_length * 2; i++)
|
||||||
|
{
|
||||||
|
JS_FreeCString(context, headers[i]);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < plen; ++i)
|
||||||
|
{
|
||||||
|
JS_FreeAtom(context, ptab[i].atom);
|
||||||
|
}
|
||||||
|
js_free(context, ptab);
|
||||||
|
JS_FreeValue(context, buffer);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
static void _httpd_callback(tf_http_request_t* request)
|
static void _httpd_callback(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
tf_printf("httpd_callback!\n");
|
|
||||||
http_handler_data_t* data = request->user_data;
|
http_handler_data_t* data = request->user_data;
|
||||||
JSValue response = JS_Call(data->context, data->callback, JS_UNDEFINED, 0, NULL);
|
JSContext* context = data->context;
|
||||||
tf_printf("%d %d\n", JS_IsUndefined(response), JS_IsException(response));
|
JSValue request_object = JS_NewObject(context);
|
||||||
tf_util_report_error(data->context, response);
|
JS_SetPropertyStr(context, request_object, "uri", JS_NewString(context, request->path));
|
||||||
JS_FreeValue(data->context, response);
|
JSValue headers = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, request_object, "headers", headers);
|
||||||
|
for (int i = 0; i < request->headers_count; i++)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue client = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, client, "tls", JS_FALSE);
|
||||||
|
JS_SetPropertyStr(context, request_object, "client", client);
|
||||||
|
|
||||||
|
JSValue response_object = JS_NewObjectClass(context, _httpd_response_class_id);
|
||||||
|
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, "end", JS_NewCFunction(context, _httpd_response_end, "end", 1));
|
||||||
|
JSValue args[] =
|
||||||
|
{
|
||||||
|
request_object,
|
||||||
|
response_object,
|
||||||
|
};
|
||||||
|
JSValue response = JS_Call(context, data->callback, JS_UNDEFINED, 2, args);
|
||||||
|
tf_util_report_error(context, response);
|
||||||
|
JS_FreeValue(context, request_object);
|
||||||
|
JS_FreeValue(context, response_object);
|
||||||
|
JS_FreeValue(context, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue _httpd_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
static JSValue _httpd_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
@ -31,7 +135,6 @@ static JSValue _httpd_all(JSContext* context, JSValueConst this_val, int argc, J
|
|||||||
http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
|
http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
|
||||||
*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
|
*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
|
||||||
tf_http_add_handler(http, pattern, _httpd_callback, data);
|
tf_http_add_handler(http, pattern, _httpd_callback, data);
|
||||||
tf_printf("HTTPD_ALL: %s\n", pattern);
|
|
||||||
JS_FreeCString(context, pattern);
|
JS_FreeCString(context, pattern);
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
@ -59,6 +162,7 @@ void _httpd_finalizer(JSRuntime* runtime, JSValue value)
|
|||||||
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);
|
||||||
JSClassDef def =
|
JSClassDef def =
|
||||||
{
|
{
|
||||||
.class_name = "Httpd",
|
.class_name = "Httpd",
|
||||||
|
Loading…
Reference in New Issue
Block a user