http+js: Move app blob handling from JS to C. handler.js support has been temporarily removed.
This commit is contained in:
		
							
								
								
									
										134
									
								
								src/httpd.js.c
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								src/httpd.js.c
									
									
									
									
									
								
							| @@ -1034,6 +1034,131 @@ static user_app_t* _parse_user_app_from_path(const char* path, const char* expec | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| typedef struct _app_blob_t | ||||
| { | ||||
| 	tf_http_request_t* request; | ||||
| 	bool found; | ||||
| 	bool not_modified; | ||||
| 	void* data; | ||||
| 	size_t size; | ||||
| 	char etag[256]; | ||||
| } app_blob_t; | ||||
|  | ||||
| static void _httpd_endpoint_app_blob_work(tf_ssb_t* ssb, void* user_data) | ||||
| { | ||||
| 	app_blob_t* data = user_data; | ||||
| 	tf_http_request_t* request = data->request; | ||||
| 	char app_id[256] = ""; | ||||
| 	const char* file = NULL; | ||||
| 	if (request->path[0] == '/' && request->path[1] == '~') | ||||
| 	{ | ||||
| 		const char* last_slash = strchr(request->path + 1, '/'); | ||||
| 		if (last_slash) | ||||
| 		{ | ||||
| 			last_slash = strchr(last_slash + 1, '/'); | ||||
| 		} | ||||
| 		user_app_t* user_app = last_slash ? _parse_user_app_from_path(request->path, last_slash) : NULL; | ||||
| 		if (user_app) | ||||
| 		{ | ||||
| 			size_t path_length = strlen("path:") + strlen(user_app->app) + 1; | ||||
| 			char* app_path = tf_malloc(path_length); | ||||
| 			snprintf(app_path, path_length, "path:%s", user_app->app); | ||||
| 			const char* value = tf_ssb_db_get_property(ssb, user_app->user, app_path); | ||||
| 			snprintf(app_id, sizeof(app_id), "%s", value); | ||||
| 			tf_free(app_path); | ||||
| 			tf_free((void*)value); | ||||
| 			file = last_slash + 1; | ||||
| 			tf_free(user_app); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (request->path[0] == '/' && request->path[1] == '&') | ||||
| 	{ | ||||
| 		const char* end = strstr(request->path, ".sha256/"); | ||||
| 		if (end) | ||||
| 		{ | ||||
| 			snprintf(app_id, sizeof(app_id), "%.*s", (int)(end + strlen(".sha256") - request->path - 1), request->path + 1); | ||||
| 			file = end + strlen(".sha256/"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	char* app_blob = NULL; | ||||
| 	size_t app_blob_size = 0; | ||||
| 	if (*app_id && tf_ssb_db_blob_get(ssb, app_id, (uint8_t**)&app_blob, &app_blob_size)) | ||||
| 	{ | ||||
| 		JSMallocFunctions funcs = { 0 }; | ||||
| 		tf_get_js_malloc_functions(&funcs); | ||||
| 		JSRuntime* runtime = JS_NewRuntime2(&funcs, NULL); | ||||
| 		JSContext* context = JS_NewContext(runtime); | ||||
|  | ||||
| 		JSValue app_object = JS_ParseJSON(context, app_blob, app_blob_size, NULL); | ||||
| 		JSValue files = JS_GetPropertyStr(context, app_object, "files"); | ||||
| 		JSValue blob_id = JS_GetPropertyStr(context, files, file); | ||||
| 		const char* blob_id_str = JS_ToCString(context, blob_id); | ||||
| 		if (blob_id_str) | ||||
| 		{ | ||||
| 			snprintf(data->etag, sizeof(data->etag), "\"%s\"", blob_id_str); | ||||
| 			const char* match = tf_http_request_get_header(data->request, "if-none-match"); | ||||
| 			if (match && strcmp(match, data->etag) == 0) | ||||
| 			{ | ||||
| 				data->not_modified = true; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				data->found = tf_ssb_db_blob_get(ssb, blob_id_str, (uint8_t**)&data->data, &data->size); | ||||
| 			} | ||||
| 		} | ||||
| 		JS_FreeCString(context, blob_id_str); | ||||
| 		JS_FreeValue(context, blob_id); | ||||
| 		JS_FreeValue(context, files); | ||||
| 		JS_FreeValue(context, app_object); | ||||
|  | ||||
| 		JS_FreeContext(context); | ||||
| 		JS_FreeRuntime(runtime); | ||||
| 		tf_free(app_blob); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void _httpd_endpoint_app_blob_after_work(tf_ssb_t* ssb, int status, void* user_data) | ||||
| { | ||||
| 	app_blob_t* data = user_data; | ||||
| 	if (data->not_modified) | ||||
| 	{ | ||||
| 		tf_http_respond(data->request, 304, NULL, 0, NULL, 0); | ||||
| 	} | ||||
| 	else if (data->found) | ||||
| 	{ | ||||
| 		const char* mime_type = _ext_to_content_type(strrchr(data->request->path, '.'), false); | ||||
| 		if (!mime_type) | ||||
| 		{ | ||||
| 			mime_type = _httpd_mime_type_from_magic_bytes_internal(data->data, data->size); | ||||
| 		} | ||||
| 		const char* headers[] = { | ||||
| 			"Access-Control-Allow-Origin", | ||||
| 			"*", | ||||
| 			"Content-Security-Policy", | ||||
| 			"sandbox allow-downloads allow-top-navigation-by-user-activation", | ||||
| 			"Content-Type", | ||||
| 			mime_type ? mime_type : "application/binary", | ||||
| 			"etag", | ||||
| 			data->etag, | ||||
| 		}; | ||||
| 		tf_http_respond(data->request, 200, headers, tf_countof(headers) / 2, data->data, data->size); | ||||
| 	} | ||||
| 	tf_free(data->data); | ||||
| 	tf_http_request_unref(data->request); | ||||
| 	tf_free(data); | ||||
| } | ||||
|  | ||||
| static void _httpd_endpoint_app_blob(tf_http_request_t* request) | ||||
| { | ||||
| 	tf_http_request_ref(request); | ||||
| 	tf_task_t* task = request->user_data; | ||||
| 	tf_ssb_t* ssb = tf_task_get_ssb(task); | ||||
| 	app_blob_t* data = tf_malloc(sizeof(app_blob_t)); | ||||
| 	*data = (app_blob_t) { .request = request }; | ||||
| 	tf_ssb_run_work(ssb, _httpd_endpoint_app_blob_work, _httpd_endpoint_app_blob_after_work, data); | ||||
| } | ||||
|  | ||||
| typedef struct _view_t | ||||
| { | ||||
| 	tf_http_request_t* request; | ||||
| @@ -2117,14 +2242,17 @@ void tf_httpd_register(JSContext* context) | ||||
| 	tf_http_add_handler(http, "/speedscope/*", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/static/*", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/.well-known/*", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256", _httpd_endpoint_add_slash, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256/", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/*/view", _httpd_endpoint_view, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256/view", _httpd_endpoint_view, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256/*", _httpd_endpoint_app_blob, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}", _httpd_endpoint_add_slash, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}/", _httpd_endpoint_static, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}/save", _httpd_endpoint_save, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}/delete", _httpd_endpoint_delete, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}/view", _httpd_endpoint_view, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}/*", _httpd_endpoint_app_blob, NULL, task); | ||||
| 	tf_http_add_handler(http, "/save", _httpd_endpoint_save, NULL, task); | ||||
| 	tf_http_add_handler(http, "/~{word}/{word}", _httpd_endpoint_add_slash, NULL, task); | ||||
| 	tf_http_add_handler(http, "/&*.sha256", _httpd_endpoint_add_slash, NULL, task); | ||||
|  | ||||
| 	tf_http_add_handler(http, "/robots.txt", _httpd_endpoint_robots_txt, NULL, NULL); | ||||
| 	tf_http_add_handler(http, "/debug", _httpd_endpoint_debug, NULL, task); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user