Document the 400 error response for originate
[asterisk/asterisk.git] / res / res_stasis_http_channels.c
index aa44819..050ef00 100644 (file)
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
 #include "stasis_http/resource_channels.h"
+#if defined(AST_DEVMODE)
+#include "stasis_http/ari_model_validators.h"
+#endif
 
 /*!
  * \brief Parameter parsing callback for /channels.
@@ -53,11 +56,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_get_channels_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_get_channels_args args = {};
        stasis_http_get_channels(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_list(response->message,
+                               ari_validate_channel_fn());
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels.
@@ -67,9 +98,14 @@ static void stasis_http_get_channels_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_originate_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_originate_args args = {};
        struct ast_variable *i;
 
@@ -83,9 +119,48 @@ static void stasis_http_originate_cb(
                if (strcmp(i->name, "context") == 0) {
                        args.context = (i->value);
                } else
+               if (strcmp(i->name, "priority") == 0) {
+                       args.priority = atol(i->value);
+               } else
+               if (strcmp(i->name, "app") == 0) {
+                       args.app = (i->value);
+               } else
+               if (strcmp(i->name, "appArgs") == 0) {
+                       args.app_args = (i->value);
+               } else
+               if (strcmp(i->name, "callerId") == 0) {
+                       args.caller_id = (i->value);
+               } else
+               if (strcmp(i->name, "timeout") == 0) {
+                       args.timeout = atoi(i->value);
+               } else
                {}
        }
        stasis_http_originate(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 400: /* Invalid parameters for originating a channel. */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}.
@@ -95,9 +170,14 @@ static void stasis_http_originate_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_get_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_get_channel_args args = {};
        struct ast_variable *i;
 
@@ -108,6 +188,30 @@ static void stasis_http_get_channel_cb(
                {}
        }
        stasis_http_get_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_channel(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}.
@@ -117,9 +221,14 @@ static void stasis_http_get_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_delete_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_delete_channel_args args = {};
        struct ast_variable *i;
 
@@ -130,6 +239,30 @@ static void stasis_http_delete_channel_cb(
                {}
        }
        stasis_http_delete_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/dial.
@@ -139,9 +272,14 @@ static void stasis_http_delete_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_dial_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_dial_args args = {};
        struct ast_variable *i;
 
@@ -155,6 +293,9 @@ static void stasis_http_dial_cb(
                if (strcmp(i->name, "context") == 0) {
                        args.context = (i->value);
                } else
+               if (strcmp(i->name, "timeout") == 0) {
+                       args.timeout = atoi(i->value);
+               } else
                {}
        }
        for (i = path_vars; i; i = i->next) {
@@ -164,6 +305,31 @@ static void stasis_http_dial_cb(
                {}
        }
        stasis_http_dial(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_dialed(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dial\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dial\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/continue.
@@ -173,12 +339,29 @@ static void stasis_http_dial_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_continue_in_dialplan_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_continue_in_dialplan_args args = {};
        struct ast_variable *i;
 
+       for (i = get_params; i; i = i->next) {
+               if (strcmp(i->name, "context") == 0) {
+                       args.context = (i->value);
+               } else
+               if (strcmp(i->name, "extension") == 0) {
+                       args.extension = (i->value);
+               } else
+               if (strcmp(i->name, "priority") == 0) {
+                       args.priority = atoi(i->value);
+               } else
+               {}
+       }
        for (i = path_vars; i; i = i->next) {
                if (strcmp(i->name, "channelId") == 0) {
                        args.channel_id = (i->value);
@@ -186,6 +369,31 @@ static void stasis_http_continue_in_dialplan_cb(
                {}
        }
        stasis_http_continue_in_dialplan(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/continue\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/continue\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/answer.
@@ -195,9 +403,14 @@ static void stasis_http_continue_in_dialplan_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_answer_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_answer_channel_args args = {};
        struct ast_variable *i;
 
@@ -208,6 +421,31 @@ static void stasis_http_answer_channel_cb(
                {}
        }
        stasis_http_answer_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/answer\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/answer\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/mute.
@@ -217,9 +455,14 @@ static void stasis_http_answer_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_mute_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_mute_channel_args args = {};
        struct ast_variable *i;
 
@@ -236,6 +479,31 @@ static void stasis_http_mute_channel_cb(
                {}
        }
        stasis_http_mute_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/unmute.
@@ -245,9 +513,14 @@ static void stasis_http_mute_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_unmute_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_unmute_channel_args args = {};
        struct ast_variable *i;
 
@@ -264,6 +537,31 @@ static void stasis_http_unmute_channel_cb(
                {}
        }
        stasis_http_unmute_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/unmute\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/unmute\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/hold.
@@ -273,9 +571,14 @@ static void stasis_http_unmute_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_hold_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_hold_channel_args args = {};
        struct ast_variable *i;
 
@@ -286,6 +589,31 @@ static void stasis_http_hold_channel_cb(
                {}
        }
        stasis_http_hold_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/unhold.
@@ -295,9 +623,14 @@ static void stasis_http_hold_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_unhold_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_unhold_channel_args args = {};
        struct ast_variable *i;
 
@@ -308,6 +641,31 @@ static void stasis_http_unhold_channel_cb(
                {}
        }
        stasis_http_unhold_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/unhold\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/unhold\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/play.
@@ -317,9 +675,14 @@ static void stasis_http_unhold_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_play_on_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_play_on_channel_args args = {};
        struct ast_variable *i;
 
@@ -327,6 +690,15 @@ static void stasis_http_play_on_channel_cb(
                if (strcmp(i->name, "media") == 0) {
                        args.media = (i->value);
                } else
+               if (strcmp(i->name, "lang") == 0) {
+                       args.lang = (i->value);
+               } else
+               if (strcmp(i->name, "offsetms") == 0) {
+                       args.offsetms = atoi(i->value);
+               } else
+               if (strcmp(i->name, "skipms") == 0) {
+                       args.skipms = atoi(i->value);
+               } else
                {}
        }
        for (i = path_vars; i; i = i->next) {
@@ -336,6 +708,31 @@ static void stasis_http_play_on_channel_cb(
                {}
        }
        stasis_http_play_on_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_playback(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/record.
@@ -345,9 +742,14 @@ static void stasis_http_play_on_channel_cb(
  * \param[out] response Response to the HTTP request.
  */
 static void stasis_http_record_channel_cb(
-    struct ast_variable *get_params, struct ast_variable *path_vars,
-    struct ast_variable *headers, struct stasis_http_response *response)
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
 {
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
        struct ast_record_channel_args args = {};
        struct ast_variable *i;
 
@@ -364,11 +766,11 @@ static void stasis_http_record_channel_cb(
                if (strcmp(i->name, "maxSilenceSeconds") == 0) {
                        args.max_silence_seconds = atoi(i->value);
                } else
-               if (strcmp(i->name, "append") == 0) {
-                       args.append = atoi(i->value);
+               if (strcmp(i->name, "ifExists") == 0) {
+                       args.if_exists = (i->value);
                } else
                if (strcmp(i->name, "beep") == 0) {
-                       args.beep = atoi(i->value);
+                       args.beep = ast_true(i->value);
                } else
                if (strcmp(i->name, "terminateOn") == 0) {
                        args.terminate_on = (i->value);
@@ -382,6 +784,151 @@ static void stasis_http_record_channel_cb(
                {}
        }
        stasis_http_record_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 400: /* Invalid parameters */
+       case 404: /* Channel not found */
+       case 409: /* Channel is not in a Stasis application; the channel is currently bridged with other channels; A recording with the same name is currently in progress. */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/record\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/record\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/variable.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void stasis_http_get_channel_var_cb(
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
+{
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
+       struct ast_get_channel_var_args args = {};
+       struct ast_variable *i;
+
+       for (i = get_params; i; i = i->next) {
+               if (strcmp(i->name, "variable") == 0) {
+                       args.variable = (i->value);
+               } else
+               {}
+       }
+       for (i = path_vars; i; i = i->next) {
+               if (strcmp(i->name, "channelId") == 0) {
+                       args.channel_id = (i->value);
+               } else
+               {}
+       }
+       stasis_http_get_channel_var(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_variable(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/variable.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void stasis_http_set_channel_var_cb(
+       struct ast_variable *get_params, struct ast_variable *path_vars,
+       struct ast_variable *headers, struct stasis_http_response *response)
+{
+#if defined(AST_DEVMODE)
+       int is_valid;
+       int code;
+#endif /* AST_DEVMODE */
+
+       struct ast_set_channel_var_args args = {};
+       struct ast_variable *i;
+
+       for (i = get_params; i; i = i->next) {
+               if (strcmp(i->name, "variable") == 0) {
+                       args.variable = (i->value);
+               } else
+               if (strcmp(i->name, "value") == 0) {
+                       args.value = (i->value);
+               } else
+               {}
+       }
+       for (i = path_vars; i; i = i->next) {
+               if (strcmp(i->name, "channelId") == 0) {
+                       args.channel_id = (i->value);
+               } else
+               {}
+       }
+       stasis_http_set_channel_var(headers, &args, response);
+#if defined(AST_DEVMODE)
+       code = response->response_code;
+
+       switch (code) {
+       case 500: /* Internal server error */
+       case 404: /* Channel not found */
+       case 409: /* Channel not in a Stasis application */
+               is_valid = 1;
+               break;
+       default:
+               if (200 <= code && code <= 299) {
+                       is_valid = ari_validate_void(
+                               response->message);
+               } else {
+                       ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
+                       is_valid = 0;
+               }
+       }
+
+       if (!is_valid) {
+               ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
+               stasis_http_response_error(response, 500,
+                       "Internal Server Error", "Response validation failed");
+       }
+#endif /* AST_DEVMODE */
 }
 
 /*! \brief REST handler for /api-docs/channels.{format} */
@@ -466,6 +1013,16 @@ static struct stasis_rest_handlers channels_channelId_record = {
        .children = {  }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
+static struct stasis_rest_handlers channels_channelId_variable = {
+       .path_segment = "variable",
+       .callbacks = {
+               [AST_HTTP_GET] = stasis_http_get_channel_var_cb,
+               [AST_HTTP_POST] = stasis_http_set_channel_var_cb,
+       },
+       .num_children = 0,
+       .children = {  }
+};
+/*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels_channelId = {
        .path_segment = "channelId",
        .is_wildcard = 1,
@@ -473,8 +1030,8 @@ static struct stasis_rest_handlers channels_channelId = {
                [AST_HTTP_GET] = stasis_http_get_channel_cb,
                [AST_HTTP_DELETE] = stasis_http_delete_channel_cb,
        },
-       .num_children = 9,
-       .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_play,&channels_channelId_record, }
+       .num_children = 10,
+       .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable, }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels = {
@@ -489,8 +1046,10 @@ static struct stasis_rest_handlers channels = {
 
 static int load_module(void)
 {
+       int res = 0;
        stasis_app_ref();
-       return stasis_http_add_handler(&channels);
+       res |= stasis_http_add_handler(&channels);
+       return res;
 }
 
 static int unload_module(void)
@@ -500,8 +1059,7 @@ static int unload_module(void)
        return 0;
 }
 
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
-       "RESTful API module - Channel resources",
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Channel resources",
        .load = load_module,
        .unload = unload_module,
        .nonoptreq = "res_stasis_http,res_stasis",