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:
		
							
								
								
									
										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)
 | 
			
		||||
	{
 | 
			
		||||
		tf_http_request_t request =
 | 
			
		||||
		tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
 | 
			
		||||
		*request = (tf_http_request_t)
 | 
			
		||||
		{
 | 
			
		||||
			.connection = connection,
 | 
			
		||||
			.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,
 | 
			
		||||
			.user_data = connection->user_data,
 | 
			
		||||
		};
 | 
			
		||||
		connection->callback(&request);
 | 
			
		||||
		connection->callback(request);
 | 
			
		||||
		_http_reset_connection(connection);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -387,8 +388,15 @@ static const char* _http_status_text(int status)
 | 
			
		||||
{
 | 
			
		||||
	switch (status)
 | 
			
		||||
	{
 | 
			
		||||
	case 101: return "Switching Protocols";
 | 
			
		||||
	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 500: return "Internal server error";
 | 
			
		||||
	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 };
 | 
			
		||||
		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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								src/httpd.js.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								src/httpd.js.c
									
									
									
									
									
								
							@@ -6,7 +6,14 @@
 | 
			
		||||
#include "task.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_response_class_id;
 | 
			
		||||
 | 
			
		||||
typedef struct _http_handler_data_t
 | 
			
		||||
{
 | 
			
		||||
@@ -14,14 +21,111 @@ typedef struct _http_handler_data_t
 | 
			
		||||
	JSValue callback;
 | 
			
		||||
} 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)
 | 
			
		||||
{
 | 
			
		||||
	tf_printf("httpd_callback!\n");
 | 
			
		||||
	http_handler_data_t* data = request->user_data;
 | 
			
		||||
	JSValue response = JS_Call(data->context, data->callback, JS_UNDEFINED, 0, NULL);
 | 
			
		||||
	tf_printf("%d %d\n", JS_IsUndefined(response), JS_IsException(response));
 | 
			
		||||
	tf_util_report_error(data->context, response);
 | 
			
		||||
	JS_FreeValue(data->context, response);
 | 
			
		||||
	JSContext* context = data->context;
 | 
			
		||||
	JSValue request_object = JS_NewObject(context);
 | 
			
		||||
	JS_SetPropertyStr(context, request_object, "uri", JS_NewString(context, request->path));
 | 
			
		||||
	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)
 | 
			
		||||
@@ -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));
 | 
			
		||||
	*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
 | 
			
		||||
	tf_http_add_handler(http, pattern, _httpd_callback, data);
 | 
			
		||||
	tf_printf("HTTPD_ALL: %s\n", pattern);
 | 
			
		||||
	JS_FreeCString(context, pattern);
 | 
			
		||||
 | 
			
		||||
	return JS_UNDEFINED;
 | 
			
		||||
@@ -59,6 +162,7 @@ void _httpd_finalizer(JSRuntime* runtime, JSValue value)
 | 
			
		||||
void tf_httpd_register(JSContext* context)
 | 
			
		||||
{
 | 
			
		||||
	JS_NewClassID(&_httpd_class_id);
 | 
			
		||||
	JS_NewClassID(&_httpd_response_class_id);
 | 
			
		||||
	JSClassDef def =
 | 
			
		||||
	{
 | 
			
		||||
		.class_name = "Httpd",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user