diff options
Diffstat (limited to 'res/res_ari.c')
-rw-r--r-- | res/res_ari.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/res/res_ari.c b/res/res_ari.c index e362a5811..549d78353 100644 --- a/res/res_ari.c +++ b/res/res_ari.c @@ -148,6 +148,7 @@ #include "asterisk/astobj2.h" #include "asterisk/module.h" #include "asterisk/paths.h" +#include "asterisk/stasis_app.h" #include <string.h> #include <sys/stat.h> @@ -491,7 +492,7 @@ static void handle_options(struct stasis_rest_handlers *handler, void ast_ari_invoke(struct ast_tcptls_session_instance *ser, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers, - struct ast_ari_response *response) + struct ast_json *body, struct ast_ari_response *response) { RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup); struct stasis_rest_handlers *handler; @@ -506,8 +507,10 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser, while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) { struct stasis_rest_handlers *found_handler = NULL; int i; + ast_uri_decode(path_segment, ast_uri_http_legacy); ast_debug(3, "Finding handler for %s\n", path_segment); + for (i = 0; found_handler == NULL && i < handler->num_children; ++i) { struct stasis_rest_handlers *child = handler->children[i]; @@ -569,7 +572,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser, return; } - callback(ser, get_params, path_vars, headers, response); + callback(ser, get_params, path_vars, headers, body, response); if (response->message == NULL && response->response_code == 0) { /* Really should not happen */ ast_log(LOG_ERROR, "ARI %s %s not implemented\n", @@ -879,6 +882,10 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup); struct ast_ari_response response = { .fd = -1, 0 }; RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy); + struct ast_variable *var; + const char *app_name = NULL; + RAII_VAR(struct ast_json *, body, ast_json_null(), ast_json_free); + int debug_app = 0; if (!response_body) { ast_http_request_close_on_completion(ser); @@ -926,6 +933,25 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, "Bad Request", "Error parsing request body"); goto request_failed; } + + /* Look for a JSON request entity only if there were no post_vars. + * If there were post_vars, then the request body would already have + * been consumed and can not be read again. + */ + body = ast_http_get_json(ser, headers); + if (!body) { + switch (errno) { + case EFBIG: + ast_ari_response_error(&response, 413, "Request Entity Too Large", "Request body too large"); + goto request_failed; + case ENOMEM: + ast_ari_response_error(&response, 500, "Internal Server Error", "Error processing request"); + goto request_failed; + case EIO: + ast_ari_response_error(&response, 400, "Bad Request", "Error parsing request body"); + goto request_failed; + } + } } if (get_params == NULL) { get_params = post_vars; @@ -942,6 +968,41 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, get_params = post_vars; } + /* At this point, get_params will contain post_vars (if any) */ + app_name = ast_variable_find_in_list(get_params, "app"); + if (!app_name) { + struct ast_json *app = ast_json_object_get(body, "app"); + + app_name = (app ? ast_json_string_get(app) : NULL); + } + + /* stasis_app_get_debug_by_name returns an "||" of the app's debug flag + * and the global debug flag. + */ + debug_app = stasis_app_get_debug_by_name(app_name); + if (debug_app) { + struct ast_str *buf = ast_str_create(512); + char *str = ast_json_dump_string_format(body, ast_ari_json_format()); + + if (!buf) { + ast_http_request_close_on_completion(ser); + ast_http_error(ser, 500, "Server Error", "Out of memory"); + goto request_failed; + } + + ast_str_append(&buf, 0, "<--- ARI request received from: %s --->\n", + ast_sockaddr_stringify(&ser->remote_address)); + for (var = headers; var; var = var->next) { + ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value); + } + for (var = get_params; var; var = var->next) { + ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value); + } + ast_verbose("%sbody:\n%s\n\n", ast_str_buffer(buf), str); + ast_json_free(str); + ast_free(buf); + } + user = authenticate_user(get_params, headers); if (response.response_code > 0) { /* POST parameter processing error. Do nothing. */ @@ -980,7 +1041,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, } } else { /* Other RESTful resources */ - ast_ari_invoke(ser, uri, method, get_params, headers, + ast_ari_invoke(ser, uri, method, get_params, headers, body, &response); } @@ -992,6 +1053,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, } request_failed: + /* If you explicitly want to have no content, set message to * ast_json_null(). */ @@ -1014,8 +1076,13 @@ request_failed: } } - ast_debug(3, "Examining ARI response:\n%d %s\n%s\n%s\n", response.response_code, - response.response_text, ast_str_buffer(response.headers), ast_str_buffer(response_body)); + if (debug_app) { + ast_verbose("<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n", + ast_sockaddr_stringify(&ser->remote_address), response.response_code, + response.response_text, ast_str_buffer(response.headers), + ast_str_buffer(response_body)); + } + ast_http_send(ser, method, response.response_code, response.response_text, response.headers, response_body, response.fd != -1 ? response.fd : 0, 0); |