mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-20 12:20:12 +00:00
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
This commit is contained in:
27
main/http.c
27
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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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).
|
||||
|
@@ -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;
|
||||
|
@@ -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": [
|
||||
|
Reference in New Issue
Block a user