|
@@ -1136,15 +1136,14 @@ mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
|
|
|
== (NUM_OPTIONS + 1),
|
|
|
"config_options and enum not sync");
|
|
|
|
|
|
-enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER, NUM_HANDLERS };
|
|
|
+enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
|
|
|
|
|
|
-struct mg_request_handler_info {
|
|
|
+struct mg_handler_info {
|
|
|
/* Name/Pattern of the URI. */
|
|
|
char *uri;
|
|
|
size_t uri_len;
|
|
|
|
|
|
- /* handler type: ws/wss (websocket) or http/https (web page) or
|
|
|
- * authorization. */
|
|
|
+ /* handler type */
|
|
|
int handler_type;
|
|
|
|
|
|
/* Handler for http/https or authorization requests. */
|
|
@@ -1156,11 +1155,14 @@ struct mg_request_handler_info {
|
|
|
mg_websocket_data_handler data_handler;
|
|
|
mg_websocket_close_handler close_handler;
|
|
|
|
|
|
+ /* Handler for authorization requests */
|
|
|
+ mg_authorization_handler auth_handler;
|
|
|
+
|
|
|
/* User supplied argument for the handler function. */
|
|
|
void *cbdata;
|
|
|
|
|
|
- /* next request handler in a linked list */
|
|
|
- struct mg_request_handler_info *next;
|
|
|
+ /* next handler in a linked list */
|
|
|
+ struct mg_handler_info *next;
|
|
|
};
|
|
|
|
|
|
struct mg_context {
|
|
@@ -1198,7 +1200,7 @@ struct mg_context {
|
|
|
char *systemName; /* What operating system is running */
|
|
|
|
|
|
/* linked list of uri handlers */
|
|
|
- struct mg_request_handler_info *request_handlers;
|
|
|
+ struct mg_handler_info *handlers;
|
|
|
|
|
|
#if defined(USE_LUA) && defined(USE_WEBSOCKET)
|
|
|
/* linked list of shared lua websockets */
|
|
@@ -9032,27 +9034,28 @@ redirect_to_https_port(struct mg_connection *conn, int ssl_index)
|
|
|
|
|
|
|
|
|
static void
|
|
|
-mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
- const char *uri,
|
|
|
- int handler_type,
|
|
|
- int is_delete_request,
|
|
|
- mg_request_handler handler,
|
|
|
- mg_websocket_connect_handler connect_handler,
|
|
|
- mg_websocket_ready_handler ready_handler,
|
|
|
- mg_websocket_data_handler data_handler,
|
|
|
- mg_websocket_close_handler close_handler,
|
|
|
- void *cbdata)
|
|
|
-{
|
|
|
- struct mg_request_handler_info *tmp_rh, **lastref;
|
|
|
+mg_set_handler_type(struct mg_context *ctx,
|
|
|
+ const char *uri,
|
|
|
+ int handler_type,
|
|
|
+ int is_delete_request,
|
|
|
+ mg_request_handler handler,
|
|
|
+ mg_websocket_connect_handler connect_handler,
|
|
|
+ mg_websocket_ready_handler ready_handler,
|
|
|
+ mg_websocket_data_handler data_handler,
|
|
|
+ mg_websocket_close_handler close_handler,
|
|
|
+ mg_authorization_handler auth_handler,
|
|
|
+ void *cbdata)
|
|
|
+{
|
|
|
+ struct mg_handler_info *tmp_rh, **lastref;
|
|
|
size_t urilen = strlen(uri);
|
|
|
- int is_websocket_handler = (handler_type == WEBSOCKET_HANDLER);
|
|
|
|
|
|
- if (is_websocket_handler) {
|
|
|
+ if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
/* assert(handler == NULL); */
|
|
|
/* assert(is_delete_request || connect_handler!=NULL ||
|
|
|
* ready_handler!=NULL || data_handler!=NULL ||
|
|
|
* close_handler!=NULL);
|
|
|
*/
|
|
|
+ /* assert(auth_handler == NULL); */
|
|
|
if (handler != NULL) {
|
|
|
return;
|
|
|
}
|
|
@@ -9062,11 +9065,15 @@ mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
&& close_handler == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
- } else {
|
|
|
+ if (auth_handler != NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else if (handler_type == REQUEST_HANDLER) {
|
|
|
/* assert(connect_handler==NULL && ready_handler==NULL &&
|
|
|
* data_handler==NULL && close_handler==NULL); */
|
|
|
/* assert(is_delete_request || (handler!=NULL));
|
|
|
*/
|
|
|
+ /* assert(auth_handler == NULL); */
|
|
|
if (connect_handler != NULL || ready_handler != NULL
|
|
|
|| data_handler != NULL
|
|
|
|| close_handler != NULL) {
|
|
@@ -9075,6 +9082,25 @@ mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
if (!is_delete_request && (handler == NULL)) {
|
|
|
return;
|
|
|
}
|
|
|
+ if (auth_handler != NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ /* assert(handler == NULL); */
|
|
|
+ /* assert(connect_handler==NULL && ready_handler==NULL &&
|
|
|
+ * data_handler==NULL && close_handler==NULL); */
|
|
|
+ /* assert(auth_handler != NULL); */
|
|
|
+ if (handler != NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (connect_handler != NULL || ready_handler != NULL
|
|
|
+ || data_handler != NULL
|
|
|
+ || close_handler != NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!is_delete_request && (auth_handler == NULL)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (!ctx) {
|
|
@@ -9084,20 +9110,21 @@ mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
mg_lock_context(ctx);
|
|
|
|
|
|
/* first try to find an existing handler */
|
|
|
- lastref = &(ctx->request_handlers);
|
|
|
- for (tmp_rh = ctx->request_handlers; tmp_rh != NULL;
|
|
|
- tmp_rh = tmp_rh->next) {
|
|
|
+ lastref = &(ctx->handlers);
|
|
|
+ for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
|
|
|
if (tmp_rh->handler_type == handler_type) {
|
|
|
if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
|
|
|
if (!is_delete_request) {
|
|
|
/* update existing handler */
|
|
|
- if (!is_websocket_handler) {
|
|
|
+ if (handler_type == REQUEST_HANDLER) {
|
|
|
tmp_rh->handler = handler;
|
|
|
- } else {
|
|
|
+ } else if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
tmp_rh->connect_handler = connect_handler;
|
|
|
tmp_rh->ready_handler = ready_handler;
|
|
|
tmp_rh->data_handler = data_handler;
|
|
|
tmp_rh->close_handler = close_handler;
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ tmp_rh->auth_handler = auth_handler;
|
|
|
}
|
|
|
tmp_rh->cbdata = cbdata;
|
|
|
} else {
|
|
@@ -9120,8 +9147,8 @@ mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- tmp_rh = (struct mg_request_handler_info *)
|
|
|
- mg_calloc(sizeof(struct mg_request_handler_info), 1);
|
|
|
+ tmp_rh =
|
|
|
+ (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
|
|
|
if (tmp_rh == NULL) {
|
|
|
mg_unlock_context(ctx);
|
|
|
mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
|
|
@@ -9135,13 +9162,15 @@ mg_set_request_handler_type(struct mg_context *ctx,
|
|
|
return;
|
|
|
}
|
|
|
tmp_rh->uri_len = urilen;
|
|
|
- if (!is_websocket_handler) {
|
|
|
+ if (handler_type == REQUEST_HANDLER) {
|
|
|
tmp_rh->handler = handler;
|
|
|
- } else {
|
|
|
+ } else if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
tmp_rh->connect_handler = connect_handler;
|
|
|
tmp_rh->ready_handler = ready_handler;
|
|
|
tmp_rh->data_handler = data_handler;
|
|
|
tmp_rh->close_handler = close_handler;
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ tmp_rh->auth_handler = auth_handler;
|
|
|
}
|
|
|
tmp_rh->cbdata = cbdata;
|
|
|
tmp_rh->handler_type = handler_type;
|
|
@@ -9158,16 +9187,17 @@ mg_set_request_handler(struct mg_context *ctx,
|
|
|
mg_request_handler handler,
|
|
|
void *cbdata)
|
|
|
{
|
|
|
- mg_set_request_handler_type(ctx,
|
|
|
- uri,
|
|
|
- REQUEST_HANDLER,
|
|
|
- handler == NULL,
|
|
|
- handler,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- cbdata);
|
|
|
+ mg_set_handler_type(ctx,
|
|
|
+ uri,
|
|
|
+ REQUEST_HANDLER,
|
|
|
+ handler == NULL,
|
|
|
+ handler,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ cbdata);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -9183,16 +9213,17 @@ mg_set_websocket_handler(struct mg_context *ctx,
|
|
|
int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
|
|
|
&& (data_handler == NULL)
|
|
|
&& (close_handler == NULL);
|
|
|
- mg_set_request_handler_type(ctx,
|
|
|
- uri,
|
|
|
- WEBSOCKET_HANDLER,
|
|
|
- is_delete_request,
|
|
|
- NULL,
|
|
|
- connect_handler,
|
|
|
- ready_handler,
|
|
|
- data_handler,
|
|
|
- close_handler,
|
|
|
- cbdata);
|
|
|
+ mg_set_handler_type(ctx,
|
|
|
+ uri,
|
|
|
+ WEBSOCKET_HANDLER,
|
|
|
+ is_delete_request,
|
|
|
+ NULL,
|
|
|
+ connect_handler,
|
|
|
+ ready_handler,
|
|
|
+ data_handler,
|
|
|
+ close_handler,
|
|
|
+ NULL,
|
|
|
+ cbdata);
|
|
|
}
|
|
|
|
|
|
void
|
|
@@ -9201,16 +9232,17 @@ mg_set_auth_handler(struct mg_context *ctx,
|
|
|
mg_request_handler handler,
|
|
|
void *cbdata)
|
|
|
{
|
|
|
- mg_set_request_handler_type(ctx,
|
|
|
- uri,
|
|
|
- AUTH_HANDLER,
|
|
|
- handler == NULL,
|
|
|
- handler,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- NULL,
|
|
|
- cbdata);
|
|
|
+ mg_set_handler_type(ctx,
|
|
|
+ uri,
|
|
|
+ AUTH_HANDLER,
|
|
|
+ handler == NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ NULL,
|
|
|
+ handler,
|
|
|
+ cbdata);
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -9221,14 +9253,14 @@ get_request_handler(struct mg_connection *conn,
|
|
|
mg_websocket_ready_handler *ready_handler,
|
|
|
mg_websocket_data_handler *data_handler,
|
|
|
mg_websocket_close_handler *close_handler,
|
|
|
+ mg_authorization_handler *auth_handler,
|
|
|
void **cbdata)
|
|
|
{
|
|
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
|
|
if (request_info) {
|
|
|
const char *uri = request_info->local_uri;
|
|
|
size_t urilen = strlen(uri);
|
|
|
- struct mg_request_handler_info *tmp_rh;
|
|
|
- int is_websocket_request = (handler_type == WEBSOCKET_HANDLER);
|
|
|
+ struct mg_handler_info *tmp_rh;
|
|
|
|
|
|
if (!conn || !conn->ctx) {
|
|
|
return 0;
|
|
@@ -9237,17 +9269,19 @@ get_request_handler(struct mg_connection *conn,
|
|
|
mg_lock_context(conn->ctx);
|
|
|
|
|
|
/* first try for an exact match */
|
|
|
- for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
|
|
|
+ for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
|
|
|
tmp_rh = tmp_rh->next) {
|
|
|
if (tmp_rh->handler_type == handler_type) {
|
|
|
if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
|
|
|
- if (is_websocket_request) {
|
|
|
+ if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
*connect_handler = tmp_rh->connect_handler;
|
|
|
*ready_handler = tmp_rh->ready_handler;
|
|
|
*data_handler = tmp_rh->data_handler;
|
|
|
*close_handler = tmp_rh->close_handler;
|
|
|
- } else {
|
|
|
+ } else if (handler_type == REQUEST_HANDLER) {
|
|
|
*handler = tmp_rh->handler;
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ *auth_handler = tmp_rh->auth_handler;
|
|
|
}
|
|
|
*cbdata = tmp_rh->cbdata;
|
|
|
mg_unlock_context(conn->ctx);
|
|
@@ -9257,18 +9291,20 @@ get_request_handler(struct mg_connection *conn,
|
|
|
}
|
|
|
|
|
|
/* next try for a partial match, we will accept uri/something */
|
|
|
- for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
|
|
|
+ for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
|
|
|
tmp_rh = tmp_rh->next) {
|
|
|
if (tmp_rh->handler_type == handler_type) {
|
|
|
if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
|
|
|
&& memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
|
|
|
- if (is_websocket_request) {
|
|
|
+ if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
*connect_handler = tmp_rh->connect_handler;
|
|
|
*ready_handler = tmp_rh->ready_handler;
|
|
|
*data_handler = tmp_rh->data_handler;
|
|
|
*close_handler = tmp_rh->close_handler;
|
|
|
- } else {
|
|
|
+ } else if (handler_type == REQUEST_HANDLER) {
|
|
|
*handler = tmp_rh->handler;
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ *auth_handler = tmp_rh->auth_handler;
|
|
|
}
|
|
|
*cbdata = tmp_rh->cbdata;
|
|
|
mg_unlock_context(conn->ctx);
|
|
@@ -9278,17 +9314,19 @@ get_request_handler(struct mg_connection *conn,
|
|
|
}
|
|
|
|
|
|
/* finally try for pattern match */
|
|
|
- for (tmp_rh = conn->ctx->request_handlers; tmp_rh != NULL;
|
|
|
+ for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
|
|
|
tmp_rh = tmp_rh->next) {
|
|
|
if (tmp_rh->handler_type == handler_type) {
|
|
|
if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
|
|
|
- if (is_websocket_request) {
|
|
|
+ if (handler_type == WEBSOCKET_HANDLER) {
|
|
|
*connect_handler = tmp_rh->connect_handler;
|
|
|
*ready_handler = tmp_rh->ready_handler;
|
|
|
*data_handler = tmp_rh->data_handler;
|
|
|
*close_handler = tmp_rh->close_handler;
|
|
|
- } else {
|
|
|
+ } else if (handler_type == REQUEST_HANDLER) {
|
|
|
*handler = tmp_rh->handler;
|
|
|
+ } else { /* AUTH_HANDLER */
|
|
|
+ *auth_handler = tmp_rh->auth_handler;
|
|
|
}
|
|
|
*cbdata = tmp_rh->cbdata;
|
|
|
mg_unlock_context(conn->ctx);
|
|
@@ -9365,7 +9403,7 @@ handle_request(struct mg_connection *conn)
|
|
|
mg_websocket_data_handler ws_data_handler = NULL;
|
|
|
mg_websocket_close_handler ws_close_handler = NULL;
|
|
|
void *callback_data = NULL;
|
|
|
- mg_request_handler auth_handler = NULL;
|
|
|
+ mg_authorization_handler auth_handler = NULL;
|
|
|
void *auth_callback_data = NULL;
|
|
|
#if !defined(NO_FILES)
|
|
|
time_t curtime = time(NULL);
|
|
@@ -9457,6 +9495,7 @@ handle_request(struct mg_connection *conn)
|
|
|
&ws_ready_handler,
|
|
|
&ws_data_handler,
|
|
|
&ws_close_handler,
|
|
|
+ NULL,
|
|
|
&callback_data)) {
|
|
|
/* 5.2.1. A callback will handle this request. All requests handled
|
|
|
* by a callback have to be considered as requests to a script
|
|
@@ -9484,11 +9523,12 @@ handle_request(struct mg_connection *conn)
|
|
|
/* 6.1. a custom authorization handler is installed */
|
|
|
if (get_request_handler(conn,
|
|
|
AUTH_HANDLER,
|
|
|
- &auth_handler,
|
|
|
NULL,
|
|
|
NULL,
|
|
|
NULL,
|
|
|
NULL,
|
|
|
+ NULL,
|
|
|
+ &auth_handler,
|
|
|
&auth_callback_data)) {
|
|
|
if (!auth_handler(conn, auth_callback_data)) {
|
|
|
return;
|
|
@@ -12047,7 +12087,7 @@ static void
|
|
|
free_context(struct mg_context *ctx)
|
|
|
{
|
|
|
int i;
|
|
|
- struct mg_request_handler_info *tmp_rh;
|
|
|
+ struct mg_handler_info *tmp_rh;
|
|
|
|
|
|
if (ctx == NULL) {
|
|
|
return;
|
|
@@ -12082,9 +12122,9 @@ free_context(struct mg_context *ctx)
|
|
|
}
|
|
|
|
|
|
/* Deallocate request handlers */
|
|
|
- while (ctx->request_handlers) {
|
|
|
- tmp_rh = ctx->request_handlers;
|
|
|
- ctx->request_handlers = tmp_rh->next;
|
|
|
+ while (ctx->handlers) {
|
|
|
+ tmp_rh = ctx->handlers;
|
|
|
+ ctx->handlers = tmp_rh->next;
|
|
|
mg_free(tmp_rh->uri);
|
|
|
mg_free(tmp_rh);
|
|
|
}
|
|
@@ -12278,7 +12318,7 @@ mg_start(const struct mg_callbacks *callbacks,
|
|
|
ctx->callbacks.exit_context = 0;
|
|
|
}
|
|
|
ctx->user_data = user_data;
|
|
|
- ctx->request_handlers = NULL;
|
|
|
+ ctx->handlers = NULL;
|
|
|
|
|
|
#if defined(USE_LUA) && defined(USE_WEBSOCKET)
|
|
|
ctx->shared_lua_websockets = 0;
|