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:
parent
d7c0ffaac4
commit
9ef909c9a1
@ -951,6 +951,9 @@ function stringResponse(response, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadSettings().then(function() {
|
loadSettings().then(function() {
|
||||||
|
if (tildefriends.https_port && gGlobalSettings.http_redirect) {
|
||||||
|
httpd.set_http_redirect(gGlobalSettings.http_redirect);
|
||||||
|
}
|
||||||
httpd.all("/login", auth.handler);
|
httpd.all("/login", auth.handler);
|
||||||
httpd.registerSocketHandler("/app/socket", app.socket);
|
httpd.registerSocketHandler("/app/socket", app.socket);
|
||||||
httpd.all("", function(request, response) {
|
httpd.all("", function(request, response) {
|
||||||
|
27
src/http.c
27
src/http.c
@ -89,6 +89,9 @@ typedef struct _tf_http_t
|
|||||||
|
|
||||||
int pending_closes;
|
int pending_closes;
|
||||||
uv_loop_t* loop;
|
uv_loop_t* loop;
|
||||||
|
|
||||||
|
void* user_data;
|
||||||
|
tf_http_cleanup_t* user_data_cleanup;
|
||||||
} tf_http_t;
|
} tf_http_t;
|
||||||
|
|
||||||
static const char* _http_connection_get_header(const tf_http_connection_t* connection, const char* name);
|
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));
|
tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
|
||||||
*request = (tf_http_request_t)
|
*request = (tf_http_request_t)
|
||||||
{
|
{
|
||||||
|
.http = connection->http,
|
||||||
.connection = connection,
|
.connection = connection,
|
||||||
.phase = k_http_callback_phase_headers_received,
|
.is_tls = connection->tls != NULL,
|
||||||
.method = connection->method,
|
.method = connection->method,
|
||||||
.path = connection->path,
|
.path = connection->path,
|
||||||
.query = connection->query,
|
.query = connection->query,
|
||||||
@ -671,6 +675,12 @@ void tf_http_destroy(tf_http_t* http)
|
|||||||
tf_free(http->connections);
|
tf_free(http->connections);
|
||||||
http->connections_count = 0;
|
http->connections_count = 0;
|
||||||
|
|
||||||
|
if (http->user_data_cleanup)
|
||||||
|
{
|
||||||
|
http->user_data_cleanup(http->user_data);
|
||||||
|
http->user_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tf_free(http);
|
tf_free(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,3 +907,18 @@ void tf_http_request_websocket_upgrade(tf_http_request_t* request)
|
|||||||
{
|
{
|
||||||
request->connection->is_websocket = true;
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
typedef struct _tf_http_connection_t tf_http_connection_t;
|
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 _tf_tls_context_t tf_tls_context_t;
|
||||||
typedef struct uv_loop_s uv_loop_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 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
|
typedef struct _tf_http_request_t
|
||||||
{
|
{
|
||||||
tf_http_callback_phase_t phase;
|
tf_http_t* http;
|
||||||
tf_http_connection_t* connection;
|
tf_http_connection_t* connection;
|
||||||
|
bool is_tls;
|
||||||
const char* method;
|
const char* method;
|
||||||
const char* path;
|
const char* path;
|
||||||
const char* query;
|
const char* query;
|
||||||
@ -34,6 +30,7 @@ typedef struct _tf_http_request_t
|
|||||||
} 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);
|
||||||
|
typedef void (tf_http_cleanup_t)(void* user_data);
|
||||||
|
|
||||||
tf_http_t* tf_http_create(uv_loop_t* loop);
|
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);
|
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);
|
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_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_ref(tf_http_request_t* request);
|
||||||
void tf_http_request_release(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);
|
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_class_id;
|
||||||
static JSClassID _httpd_request_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
|
typedef struct _http_handler_data_t
|
||||||
{
|
{
|
||||||
JSContext* context;
|
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)
|
static void _httpd_callback(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
|
if (_httpd_redirect(request))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_httpd_callback_internal(request, false);
|
_httpd_callback_internal(request, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _httpd_websocket_callback(tf_http_request_t* request)
|
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_connection = tf_http_request_get_header(request, "connection");
|
||||||
const char* header_upgrade = tf_http_request_get_header(request, "upgrade");
|
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");
|
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);
|
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)
|
void _httpd_finalizer(JSRuntime* runtime, JSValue value)
|
||||||
{
|
{
|
||||||
tf_http_t* http = JS_GetOpaque(value, _httpd_class_id);
|
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, "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, "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, "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_SetPropertyStr(context, global, "httpd", httpd);
|
||||||
JS_FreeValue(context, global);
|
JS_FreeValue(context, global);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user