diff options
author | Kevin Harwell <kharwell@digium.com> | 2013-12-13 17:19:23 +0000 |
---|---|---|
committer | Kevin Harwell <kharwell@digium.com> | 2013-12-13 17:19:23 +0000 |
commit | f425c4a086526d8f4da91d62a5e02121c09609b8 (patch) | |
tree | 9c7c9ca6947d63c5037287e7bbbe4d074c7e777e | |
parent | ce18946de46a6f16463391a9c07af02b8ee4e925 (diff) |
ARI: Allow specifying channel variables during a POST /channels
Added the ability to specify channel variables when creating/originating a
channel in ARI. The variables are sent in the body of the request and should
be formatted as a single level JSON object. No nested objects allowed.
For example: {"variable1": "foo", "variable2": "bar"}.
(closes issue ASTERISK-22872)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/3052/
........
Merged revisions 403752 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403757 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | main/http.c | 27 | ||||
-rw-r--r-- | res/ari/resource_channels.c | 44 | ||||
-rw-r--r-- | res/ari/resource_channels.h | 2 | ||||
-rw-r--r-- | res/res_ari_channels.c | 35 | ||||
-rw-r--r-- | rest-api/api-docs/channels.json | 8 |
5 files changed, 75 insertions, 41 deletions
diff --git a/main/http.c b/main/http.c index 0c9b09a90..ebe0a636a 100644 --- a/main/http.c +++ b/main/http.c @@ -608,18 +608,30 @@ void ast_http_uri_unlink_all_with_key(const char *key) #define MAX_POST_CONTENT 1025 -static const char *get_content_type(struct ast_variable *headers) +/*! + * \brief Retrieves the content type specified in the "Content-Type" header. + * + * This function only returns the "type/subtype" and any trailing parameter is + * not included. + * + * \note the return value is an allocated string that needs to be freed. + * + * \retval the content type/subtype or NULL if the header is not found. + */ +static char *get_content_type(struct ast_variable *headers) { struct ast_variable *v; for (v = headers; v; v = v->next) { if (strcasecmp(v->name, "Content-Type") == 0) { - return v->value; + const char *param = strchr(v->value, ';'); + size_t size = (param ? param - v->value : + strlen(v->value)) + 1; + return ast_strndup(v->value, size); } } - /* Missing content type; assume empty string */ - return ""; + return NULL; } static int get_content_length(struct ast_variable *headers) @@ -643,11 +655,12 @@ struct ast_json *ast_http_get_json( int res; struct ast_json *body; RAII_VAR(char *, buf, NULL, ast_free); + RAII_VAR(char *, type, get_content_type(headers), ast_free); /* Use errno to distinguish errors from no body */ errno = 0; - if (strcasecmp(get_content_type(headers), "application/json") != 0) { + if (ast_strlen_zero(type) || strcasecmp(type, "application/json")) { /* Content type is not JSON */ return NULL; } @@ -704,12 +717,14 @@ struct ast_variable *ast_http_get_post_vars( struct ast_variable *v, *post_vars=NULL, *prev = NULL; char *var, *val; RAII_VAR(char *, buf, NULL, ast_free_ptr); + RAII_VAR(char *, type, get_content_type(headers), ast_free); int res; /* Use errno to distinguish errors from no params */ errno = 0; - if (strcasecmp(get_content_type(headers), "application/x-www-form-urlencoded") != 0) { + if (ast_strlen_zero(type) || + strcasecmp(type, "application/x-www-form-urlencoded")) { /* Content type is not form data */ return NULL; } diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index 824c5e660..6d85781da 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -688,6 +688,43 @@ void ast_ari_channels_list(struct ast_variable *headers, ast_ari_response_ok(response, ast_json_ref(json)); } +static int ari_channels_set_channel_var(struct ast_channel *chan, + const char *variable, const char *value, struct ast_ari_response *response) +{ + if (pbx_builtin_setvar_helper(chan, variable, value)) { + ast_ari_response_error( + response, 400, "Bad Request", + "Unable to set channel variable %s=%s", variable, value); + return -1; + } + + return 0; +} + +static int ari_channels_set_channel_vars(struct ast_channel *chan, + struct ast_json *variables, struct ast_ari_response *response) +{ + struct ast_json_iter *i; + + if (!variables) { + /* nothing to do */ + return 0; + } + + for (i = ast_json_object_iter(variables); i; + i = ast_json_object_iter_next(variables, i)) { + if (ari_channels_set_channel_var( + chan, ast_json_object_iter_key(i), + ast_json_string_get(ast_json_object_iter_value(i)), + response)) { + /* response filled in by called function */ + return -1; + } + } + + return 0; +} + void ast_ari_channels_originate(struct ast_variable *headers, struct ast_ari_channels_originate_args *args, struct ast_ari_response *response) @@ -768,6 +805,11 @@ void ast_ari_channels_originate(struct ast_variable *headers, return; } + if (ari_channels_set_channel_vars(chan, args->variables, response)) { + /* response filled in by called function */ + return; + } + snapshot = ast_channel_snapshot_create(chan); ast_channel_unlock(chan); @@ -917,4 +959,4 @@ void ast_ari_channels_snoop_channel(struct ast_variable *headers, struct ast_ari snapshot = ast_channel_snapshot_create(snoop); ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL)); -}
\ No newline at end of file +} diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h index 49ab8eb34..36c7339ba 100644 --- a/res/ari/resource_channels.h +++ b/res/ari/resource_channels.h @@ -68,6 +68,8 @@ struct ast_ari_channels_originate_args { const char *caller_id; /*! \brief Timeout (in seconds) before giving up dialing, or -1 for no timeout. */ int timeout; + /*! \brief Variables to be set on the channel. */ + struct ast_json *variables; }; /*! * \brief Create a new channel (originate). diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c index 40ad32b2b..6b741b04c 100644 --- a/res/res_ari_channels.c +++ b/res/res_ari_channels.c @@ -117,7 +117,6 @@ static void ast_ari_channels_originate_cb( struct ast_ari_channels_originate_args args = {}; struct ast_variable *i; RAII_VAR(struct ast_json *, body, NULL, ast_json_unref); - struct ast_json *field; #if defined(AST_DEVMODE) int is_valid; int code; @@ -165,39 +164,7 @@ static void ast_ari_channels_originate_cb( goto fin; } } - /* Parse query parameters out of it */ - field = ast_json_object_get(body, "endpoint"); - if (field) { - args.endpoint = ast_json_string_get(field); - } - field = ast_json_object_get(body, "extension"); - if (field) { - args.extension = ast_json_string_get(field); - } - field = ast_json_object_get(body, "context"); - if (field) { - args.context = ast_json_string_get(field); - } - field = ast_json_object_get(body, "priority"); - if (field) { - args.priority = ast_json_integer_get(field); - } - field = ast_json_object_get(body, "app"); - if (field) { - args.app = ast_json_string_get(field); - } - field = ast_json_object_get(body, "appArgs"); - if (field) { - args.app_args = ast_json_string_get(field); - } - field = ast_json_object_get(body, "callerId"); - if (field) { - args.caller_id = ast_json_string_get(field); - } - field = ast_json_object_get(body, "timeout"); - if (field) { - args.timeout = ast_json_integer_get(field); - } + args.variables = ast_json_ref(body); ast_ari_channels_originate(headers, &args, response); #if defined(AST_DEVMODE) code = response->response_code; diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json index 39586689f..263d5ada6 100644 --- a/rest-api/api-docs/channels.json +++ b/rest-api/api-docs/channels.json @@ -88,6 +88,14 @@ "allowMultiple": false, "dataType": "int", "defaultValue": 30 + }, + { + "name": "variables", + "description": "Variables to be set on the channel.", + "paramType": "body", + "required": false, + "allowMultiple": false, + "dataType": "containers" } ], "errorResponses": [ |