Reimplement http -> https redirects. Remove request phases. With just a little extra storage, it wasn't needed.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4723 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										27
									
								
								src/http.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/http.c
									
									
									
									
									
								
							| @@ -89,6 +89,9 @@ typedef struct _tf_http_t | ||||
|  | ||||
| 	int pending_closes; | ||||
| 	uv_loop_t* loop; | ||||
|  | ||||
| 	void* user_data; | ||||
| 	tf_http_cleanup_t* user_data_cleanup; | ||||
| } tf_http_t; | ||||
|  | ||||
| static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name); | ||||
| @@ -337,8 +340,9 @@ static void _http_add_body_bytes(tf_http_connection_t* connection, const void* d | ||||
| 			tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t)); | ||||
| 			*request = (tf_http_request_t) | ||||
| 			{ | ||||
| 				.http = connection->http, | ||||
| 				.connection = connection, | ||||
| 				.phase = k_http_callback_phase_headers_received, | ||||
| 				.is_tls = connection->tls != NULL, | ||||
| 				.method = connection->method, | ||||
| 				.path = connection->path, | ||||
| 				.query = connection->query, | ||||
| @@ -671,6 +675,12 @@ void tf_http_destroy(tf_http_t* http) | ||||
| 	tf_free(http->connections); | ||||
| 	http->connections_count = 0; | ||||
|  | ||||
| 	if (http->user_data_cleanup) | ||||
| 	{ | ||||
| 		http->user_data_cleanup(http->user_data); | ||||
| 		http->user_data = NULL; | ||||
| 	} | ||||
|  | ||||
| 	tf_free(http); | ||||
| } | ||||
|  | ||||
| @@ -897,3 +907,18 @@ void tf_http_request_websocket_upgrade(tf_http_request_t* request) | ||||
| { | ||||
| 	request->connection->is_websocket = true; | ||||
| } | ||||
|  | ||||
| void tf_http_set_user_data(tf_http_t* http, void* user_data, tf_http_cleanup_t* cleanup) | ||||
| { | ||||
| 	if (http->user_data && http->user_data_cleanup) | ||||
| 	{ | ||||
| 		http->user_data_cleanup(http->user_data); | ||||
| 	} | ||||
| 	http->user_data = user_data; | ||||
| 	http->user_data_cleanup = cleanup; | ||||
| } | ||||
|  | ||||
| void* tf_http_get_user_data(tf_http_t* http) | ||||
| { | ||||
| 	return http->user_data; | ||||
| } | ||||
|   | ||||
							
								
								
									
										14
									
								
								src/http.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/http.h
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
|  | ||||
| typedef struct _tf_http_connection_t tf_http_connection_t; | ||||
| @@ -8,18 +9,13 @@ typedef struct _tf_http_t tf_http_t; | ||||
| typedef struct _tf_tls_context_t tf_tls_context_t; | ||||
| typedef struct uv_loop_s uv_loop_t; | ||||
|  | ||||
| typedef enum _tf_http_callback_phase_t | ||||
| { | ||||
| 	k_http_callback_phase_headers_received, | ||||
| 	k_http_callback_phase_request_done, | ||||
| } tf_http_callback_phase_t; | ||||
|  | ||||
| typedef void (tf_http_message_callback)(tf_http_request_t* request, int op_code, const void* data, size_t size); | ||||
|  | ||||
| typedef struct _tf_http_request_t | ||||
| { | ||||
| 	tf_http_callback_phase_t phase; | ||||
| 	tf_http_t* http; | ||||
| 	tf_http_connection_t* connection; | ||||
| 	bool is_tls; | ||||
| 	const char* method; | ||||
| 	const char* path; | ||||
| 	const char* query; | ||||
| @@ -34,6 +30,7 @@ typedef struct _tf_http_request_t | ||||
| } tf_http_request_t; | ||||
|  | ||||
| typedef void (tf_http_callback_t)(tf_http_request_t* request); | ||||
| typedef void (tf_http_cleanup_t)(void* user_data); | ||||
|  | ||||
| tf_http_t* tf_http_create(uv_loop_t* loop); | ||||
| int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls); | ||||
| @@ -42,6 +39,9 @@ void tf_http_respond(tf_http_request_t* request, int status, const char** header | ||||
| 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_set_user_data(tf_http_t* http, void* user_data, tf_http_cleanup_t* cleanup); | ||||
| void* tf_http_get_user_data(tf_http_t* http); | ||||
|  | ||||
| void tf_http_request_ref(tf_http_request_t* request); | ||||
| void tf_http_request_release(tf_http_request_t* request); | ||||
| const char* tf_http_request_get_header(tf_http_request_t* request, const char* name); | ||||
|   | ||||
| @@ -21,6 +21,11 @@ | ||||
| static JSClassID _httpd_class_id; | ||||
| static JSClassID _httpd_request_class_id; | ||||
|  | ||||
| typedef struct _http_user_data_t | ||||
| { | ||||
| 	char redirect[1024]; | ||||
| } http_user_data_t; | ||||
|  | ||||
| typedef struct _http_handler_data_t | ||||
| { | ||||
| 	JSContext* context; | ||||
| @@ -217,13 +222,42 @@ static void _httpd_callback_internal(tf_http_request_t* request, bool is_websock | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static bool _httpd_redirect(tf_http_request_t* request) | ||||
| { | ||||
| 	if (request->is_tls) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	http_user_data_t* user_data = tf_http_get_user_data(request->http); | ||||
| 	if (!user_data || !*user_data->redirect) | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	char redirect[1024]; | ||||
| 	snprintf(redirect, sizeof(redirect), "%s%s", user_data->redirect, request->path); | ||||
| 	tf_http_respond(request, 303, (const char*[]) { "Location", redirect }, 1, NULL, 0); | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static void _httpd_callback(tf_http_request_t* request) | ||||
| { | ||||
| 	if (_httpd_redirect(request)) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	_httpd_callback_internal(request, false); | ||||
| } | ||||
|  | ||||
| static void _httpd_websocket_callback(tf_http_request_t* request) | ||||
| { | ||||
| 	if (_httpd_redirect(request)) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	const char* header_connection = tf_http_request_get_header(request, "connection"); | ||||
| 	const char* header_upgrade = tf_http_request_get_header(request, "upgrade"); | ||||
| 	const char* header_sec_websocket_key = tf_http_request_get_header(request, "sec-websocket-key"); | ||||
| @@ -297,6 +331,28 @@ static JSValue _httpd_start(JSContext* context, JSValueConst this_val, int argc, | ||||
| 	return JS_NewInt32(context, assigned_port); | ||||
| } | ||||
|  | ||||
| static void _httpd_free_user_data(void* user_data) | ||||
| { | ||||
| 	tf_free(user_data); | ||||
| } | ||||
|  | ||||
| static JSValue _httpd_set_http_redirect(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) | ||||
| { | ||||
| 	tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id); | ||||
| 	http_user_data_t* user_data = tf_http_get_user_data(http); | ||||
| 	if (!user_data) | ||||
| 	{ | ||||
| 		user_data = tf_malloc(sizeof(http_user_data_t)); | ||||
| 		memset(user_data, 0, sizeof(http_user_data_t)); | ||||
| 		tf_http_set_user_data(http, user_data, _httpd_free_user_data); | ||||
| 	} | ||||
|  | ||||
| 	const char* redirect = JS_ToCString(context, argv[0]); | ||||
| 	snprintf(user_data->redirect, sizeof(user_data->redirect), "%s", redirect ? redirect : ""); | ||||
| 	JS_FreeCString(context, redirect); | ||||
| 	return JS_UNDEFINED; | ||||
| } | ||||
|  | ||||
| void _httpd_finalizer(JSRuntime* runtime, JSValue value) | ||||
| { | ||||
| 	tf_http_t* http = JS_GetOpaque(value, _httpd_class_id); | ||||
| @@ -343,6 +399,7 @@ void tf_httpd_register(JSContext* context) | ||||
| 	JS_SetPropertyStr(context, httpd, "all", JS_NewCFunction(context, _httpd_all, "all", 2)); | ||||
| 	JS_SetPropertyStr(context, httpd, "registerSocketHandler", JS_NewCFunction(context, _httpd_register_socket_handler, "register_socket_handler", 2)); | ||||
| 	JS_SetPropertyStr(context, httpd, "start", JS_NewCFunction(context, _httpd_start, "start", 2)); | ||||
| 	JS_SetPropertyStr(context, httpd, "set_http_redirect", JS_NewCFunction(context, _httpd_set_http_redirect, "set_http_redirect", 1)); | ||||
| 	JS_SetPropertyStr(context, global, "httpd", httpd); | ||||
| 	JS_FreeValue(context, global); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user