[asterisk-commits] dlee: branch dlee/stasis-http r382976 - in /team/dlee/stasis-http: include/as...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 12 17:14:11 CDT 2013


Author: dlee
Date: Tue Mar 12 17:14:08 2013
New Revision: 382976

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382976
Log:
Clean up; extracted common code

Modified:
    team/dlee/stasis-http/include/asterisk/stasis_http.h
    team/dlee/stasis-http/res/res_stasis_http.c
    team/dlee/stasis-http/res/stasis_http/resource_channels.c

Modified: team/dlee/stasis-http/include/asterisk/stasis_http.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/stasis_http.h?view=diff&rev=382976&r1=382975&r2=382976
==============================================================================
--- team/dlee/stasis-http/include/asterisk/stasis_http.h (original)
+++ team/dlee/stasis-http/include/asterisk/stasis_http.h Tue Mar 12 17:14:08 2013
@@ -136,4 +136,37 @@
  */
 void stasis_websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers);
 
+/*!
+ * \brief Fill in an error \a stasis_http_response.
+ * \param response Response to fill in.
+ * \param response_code HTTP response code.
+ * \param response_text Text corresponding to the HTTP response code.
+ * \param message_fmt Error message format string.
+ */
+void stasis_http_response_error(struct stasis_http_response *response,
+				int response_code,
+				const char *response_text,
+				const char *message_fmt, ...)
+__attribute__((format(printf, 4, 5)));
+
+/*!
+ * \brief Fill in an \c OK (200) \a stasis_http_response.
+ * \param response Response to fill in.
+ * \param message JSON response.  This reference is stolen, so just \ref
+ *                ast_json_incref if you need to keep a reference to it.
+ */
+void stasis_http_response_ok(struct stasis_http_response *response,
+			     struct ast_json *message);
+
+/*!
+ * \brief Fill in a <tt>No Content</tt> (204) \a stasis_http_response.
+ */
+void stasis_http_response_no_content(struct stasis_http_response *response);
+
+/*!
+ * \brief Fill in \a response with a 500 message for allocation failures.
+ * \param response Response to fill in.
+ */
+void stasis_http_response_alloc_failed(struct stasis_http_response *response);
+
 #endif /* _ASTERISK_STASIS_HTTP_H */

Modified: team/dlee/stasis-http/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/res_stasis_http.c?view=diff&rev=382976&r1=382975&r2=382976
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_http.c (original)
+++ team/dlee/stasis-http/res/res_stasis_http.c Tue Mar 12 17:14:08 2013
@@ -83,39 +83,48 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-/*! Handler for root RESTful resource */
+/*! Handler for root RESTful resource. */
 static struct stasis_rest_handlers *root_handler;
 
-/*!
- * \internal
- * \brief Fill in an error \a stasis_http_response.
- * \param response Response to fill in.
- * \param message Error message.
- * \param response_code HTTP response code.
- * \param response_text Text corresponding to the HTTP response code.
- */
-static void response_error(struct stasis_http_response *response,
-			   const char *message,
-			   int response_code,
-			   const char *response_text)
-{
-	response->message = ast_json_pack("{s: s}", "message", message);
+/*! Pre-defined message for allocation failures. */
+static struct ast_json *alloc_failed_message;
+
+void stasis_http_response_error(struct stasis_http_response *response,
+				int response_code,
+				const char *response_text,
+				const char *message_fmt, ...)
+{
+	RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+	va_list ap;
+
+	va_start(ap, message_fmt);
+	message = ast_json_vstringf(message_fmt, ap);
+	response->message = ast_json_pack("{s: o}",
+					  "message", ast_json_ref(message));
 	response->response_code = response_code;
 	response->response_text = response_text;
 }
 
-/*!
- * \internal
- * \brief Fill in an OK \a stasis_http_response.
- * \param response Response to fill in. This reference is stolen, so just
- *                 \ref ast_json_incref if you need to keep a reference to it.
- * \param message JSON response.
- */
-static void response_ok(struct stasis_http_response *response, struct ast_json *message)
+void stasis_http_response_ok(struct stasis_http_response *response,
+			     struct ast_json *message)
 {
 	response->message = message;
 	response->response_code = 200;
 	response->response_text = "OK";
+}
+
+void stasis_http_response_no_content(struct stasis_http_response *response)
+{
+	response->message = NULL;
+	response->response_code = 204;
+	response->response_text = "No Content";
+}
+
+void stasis_http_response_alloc_failed(struct stasis_http_response *response)
+{
+	response->message = ast_json_ref(alloc_failed_message);
+	response->response_code = 500;
+	response->response_text = "Internal Server Error";
 }
 
 static void add_allow_header(struct stasis_rest_handlers *handler,
@@ -160,8 +169,7 @@
 		allow = ast_str_create(20);
 
 		if (!allow) {
-			response_error(response, "Allocation failed", 500,
-				       "Internal Server Error");
+			stasis_http_response_alloc_failed(response);
 			return;
 		}
 
@@ -227,7 +235,9 @@
 		if (found_handler == NULL) {
 			/* resource not found */
 			ast_debug(3, "  Handler not found\n");
-			response_error(response, "Resource not found", 404, "Not Found");
+			stasis_http_response_error(
+				response, 404, "Not Found",
+				"Resource not found");
 			return;
 		} else {
 			ast_debug(3, "  Got it!\n");
@@ -243,14 +253,18 @@
 
 	if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
 		add_allow_header(handler, response);
-		response_error(response, "Invalid method", 405, "Method Not Allowed");
+		stasis_http_response_error(
+			response, 405, "Method Not Allowed",
+			"Invalid method");
 		return;
 	}
 
 	callback = handler->callbacks[method];
 	if (callback == NULL) {
 		add_allow_header(handler, response);
-		response_error(response, "Unsupported method", 405, "Method Not Allowed");
+		stasis_http_response_error(
+			response, 405, "Method Not Allowed",
+			"Invalid method");
 		return;
 	}
 
@@ -258,12 +272,16 @@
 	if (response->message == NULL && response->response_code == 0) {
 		/* Really should not happen */
 		ast_assert(0);
-		response_error(response, "Method not implemented", 418, "I'm a teapot");
-	}
-}
-
-void stasis_http_get_docs(const char *uri, struct ast_variable *headers, struct stasis_http_response *response) {
-	RAII_VAR(struct ast_str *, absolute_path_builder, ast_str_create(80), ast_free);
+		stasis_http_response_error(
+			response, 418, "I'm a teapot",
+			"Method not implemented");
+	}
+}
+
+void stasis_http_get_docs(const char *uri, struct ast_variable *headers,
+			  struct stasis_http_response *response)
+{
+	RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
 	RAII_VAR(char *, absolute_api_dirname, NULL, free);
 	RAII_VAR(char *, absolute_filename, NULL, free);
 	struct ast_json *obj = NULL;
@@ -273,9 +291,9 @@
 
 	ast_debug(3, "%s(%s)\n", __func__, uri);
 
+	absolute_path_builder = ast_str_create(80);
 	if (absolute_path_builder == NULL) {
-		ast_log(LOG_ERROR, "Allocation failed\n");
-		response_error(response, "Allocation failed", 500, "Internal Server Error");
+		stasis_http_response_alloc_failed(response);
 		return;
 	}
 
@@ -285,7 +303,9 @@
 	absolute_api_dirname = realpath(ast_str_buffer(absolute_path_builder), NULL);
 	if (absolute_api_dirname == NULL) {
 		ast_log(LOG_ERROR, "Error determining real directory for rest-api\n");
-		response_error(response, "Cannot find rest-api directory", 500, "Internal Server Error");
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Cannot find rest-api directory");
 		return;
 	}
 
@@ -297,14 +317,22 @@
 		case ENAMETOOLONG:
 		case ENOENT:
 		case ENOTDIR:
-			response_error(response, "Resource not found", 404, "Not Found");
+			stasis_http_response_error(
+				response, 404, "Not Found",
+				"Resource not found");
 			break;
 		case EACCES:
-			response_error(response, "Permission denied", 403, "Forbidden");
+			stasis_http_response_error(
+				response, 403, "Forbidden",
+				"Permission denied");
 			break;
 		default:
-			ast_log(LOG_ERROR, "Error determining real path for uri '%s': %s\n", uri, strerror(errno));
-			response_error(response, "Cannot find file", 500, "Internal Server Error");
+			ast_log(LOG_ERROR,
+				"Error determining real path for uri '%s': %s\n",
+				uri, strerror(errno));
+			stasis_http_response_error(
+				response, 500, "Internal Server Error",
+				"Cannot find file");
 			break;
 		}
 		return;
@@ -312,27 +340,37 @@
 
 	if (!ast_begins_with(absolute_filename, absolute_api_dirname)) {
 		/* HACKERZ! */
-		ast_log(LOG_ERROR, "Invalid attempt to access '%s' (not in %s)\n", absolute_filename, absolute_api_dirname);
-		response_error(response, "Resource not found", 404, "Not Found");
+		ast_log(LOG_ERROR,
+			"Invalid attempt to access '%s' (not in %s)\n",
+			absolute_filename, absolute_api_dirname);
+		stasis_http_response_error(
+			response, 404, "Not Found",
+			"Resource not found");
 		return;
 	}
 
 	if (stat(absolute_filename, &file_stat) == 0) {
 		if (!(file_stat.st_mode & S_IFREG)) {
 			/* Not a file */
-			response_error(response, "Invalid access", 403, "Forbidden");
+			stasis_http_response_error(
+				response, 403, "Forbidden",
+				"Invalid access");
 			return;
 		}
 	} else {
 		/* Does not exist */
-		response_error(response, "Resource not found", 404, "Not Found");
+		stasis_http_response_error(
+			response, 404, "Not Found",
+			"Resource not found");
 		return;
 	}
 
 	/* Load resource object from file */
 	obj = ast_json_load_new_file(absolute_filename, &error);
 	if (obj == NULL) {
-		response_error(response, "Yikes! Cannot parse resource", 500, "Internal Server Error");
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Yikes! Cannot parse resource");
 		return;
 	}
 
@@ -344,14 +382,28 @@
 			}
 		}
 		if (host != NULL) {
-			ast_json_object_set(obj, "basePath", ast_json_stringf("http://%s/stasis", host->value));
+			ast_json_object_set(
+				obj, "basePath",
+				ast_json_stringf("http://%s/stasis", host->value));
 		} else {
 			/* Without the host, we don't have the basePath */
 			ast_json_object_del(obj, "basePath");
 		}
 	}
 
-	response_ok(response, obj);
+	stasis_http_response_ok(response, obj);
+}
+
+static void remove_trailing_slash(const char *uri,
+				  struct stasis_http_response *response)
+{
+	char *slashless = ast_strdupa(uri);
+	slashless[strlen(slashless) - 1] = '\0';
+
+	ast_str_append(&response->headers, 0,
+		       "Location: /stasis/%s\r\n", slashless);
+	stasis_http_response_error(response, 302, "Found",
+				   "Redirecting to %s", slashless);
 }
 
 /*!
@@ -381,22 +433,13 @@
 	int ret = 0;
 
 	if (!response_headers || !response_body) {
-		ast_log(LOG_ERROR, "Allocation failure!\n");
 		return -1;
 	}
 
 	response.headers = ast_str_create(40);
 
 	if (ast_ends_with(uri, "/")) {
-		char *slashless = ast_strdupa(uri);
-		slashless[strlen(slashless) - 1] = '\0';
-
-		ast_str_append(&response_headers, 0,
-			       "Location: /stasis/%s\r\n", slashless);
-
-		response.message = ast_json_pack("{s: o}", "message", ast_json_stringf("Redirecting to %s", slashless));
-		response.response_code = 302;
-		response.response_text = "Found";
+		remove_trailing_slash(uri, &response);
 	} else if (ast_begins_with(uri, "api/")) {
 		/* Other RESTful resources */
 		stasis_http_invoke(uri, method, get_params, headers, &response);
@@ -472,6 +515,9 @@
 {
 	int r = 0;
 
+	alloc_failed_message = ast_json_pack("{s: s}",
+					     "message", "Allocation failed");
+
 	stasis_set_root_handler(stasis_default_root_handler());
 	r |= ast_http_uri_link(&http_uri);
 	return r;
@@ -481,6 +527,8 @@
 {
 	int r = 0;
 
+	ast_json_unref(alloc_failed_message);
+	alloc_failed_message = NULL;
 	ast_http_uri_unlink(&http_uri);
 	return r;
 }

Modified: team/dlee/stasis-http/res/stasis_http/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/stasis_http/resource_channels.c?view=diff&rev=382976&r1=382975&r2=382976
==============================================================================
--- team/dlee/stasis-http/res/stasis_http/resource_channels.c (original)
+++ team/dlee/stasis-http/res/stasis_http/resource_channels.c Tue Mar 12 17:14:08 2013
@@ -34,41 +34,6 @@
 #include "asterisk/app_stasis.h"
 #include "asterisk/channel.h"
 #include "resource_channels.h"
-
-static void fill_error(struct stasis_http_response *response, int response_code,
-		       const char *response_text, const char *message)
-{
-	response->message = ast_json_pack("{s: s}", "message", message);
-	if (response->message) {
-		response->response_code = response_code;
-		response->response_text = response_text;
-	} else {
-		/* Error sending the error; great. */
-		response->response_code = 500;
-		response->response_text = "Internal Server Error";
-		response->message =
-			ast_json_pack("{s: s}", "message", "Allocation failed");
-	}
-}
-
-static void fill_ok(struct stasis_http_response *response,
-		    struct ast_json *message)
-{
-	if (!message) {
-		fill_error(response, 500, "Internal Server Error",
-			   "Allocation failed");
-	}
-
-	response->response_code = 200;
-	response->response_text = "OK";
-	response->message = message;
-}
-
-static void fill_no_content(struct stasis_http_response *response)
-{
-	response->response_code = 204;
-	response->response_text = "No Content";
-}
 
 /*!
  * \brief Finds the control object for a channel, filling the response with an
@@ -92,12 +57,12 @@
 		RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
 		chan = ast_channel_get_by_name(channel_id);
 		if (chan == NULL) {
-			fill_error(response, 404, "Not Found",
+			stasis_http_response_error(response, 404, "Not Found",
 				   "Channel not found");
 			return NULL;
 		}
 
-		fill_error(response, 409, "Conflict",
+		stasis_http_response_error(response, 409, "Conflict",
 			   "Channel not in Stasis application");
 		return NULL;
 	}
@@ -111,7 +76,10 @@
 	ast_log(LOG_ERROR, "TODO: stasis_http_dial\n");
 }
 
-void stasis_http_continue_in_dialplan(struct ast_variable *headers, struct ast_continue_in_dialplan_args *args, struct stasis_http_response *response)
+void stasis_http_continue_in_dialplan(
+	struct ast_variable *headers,
+	struct ast_continue_in_dialplan_args *args,
+	struct stasis_http_response *response)
 {
 	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
 
@@ -123,7 +91,7 @@
 	}
 
 	stasis_app_control_continue(control);
-	fill_no_content(response);
+	stasis_http_response_no_content(response);
 }
 
 void stasis_http_reject_channel(struct ast_variable *headers, struct ast_reject_channel_args *args, struct stasis_http_response *response)
@@ -143,12 +111,13 @@
 	}
 
 	if (stasis_app_control_answer(control) != 0) {
-		fill_error(response, 500, "Internal Server Error",
-			   "Failed to answer channel");
-		return;
-	}
-
-	fill_no_content(response);
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Failed to answer channel");
+		return;
+	}
+
+	stasis_http_response_no_content(response);
 }
 
 void stasis_http_mute_channel(struct ast_variable *headers, struct ast_mute_channel_args *args, struct stasis_http_response *response)
@@ -163,7 +132,9 @@
 {
 	ast_log(LOG_ERROR, "TODO: stasis_http_record_channel\n");
 }
-void stasis_http_get_channel(struct ast_variable *headers, struct ast_get_channel_args *args, struct stasis_http_response *response)
+void stasis_http_get_channel(struct ast_variable *headers,
+			     struct ast_get_channel_args *args,
+			     struct stasis_http_response *response)
 {
 	RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
 	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
@@ -171,21 +142,27 @@
 
 	caching_topic = ast_channel_topic_all_cached();
 	if (!caching_topic) {
-		fill_error(response, 500, "Internal Server Error", "Message bus not initialized");
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Message bus not initialized");
 		return;
 	}
 	ao2_ref(caching_topic, +1);
 
-	msg = stasis_cache_get(caching_topic, ast_channel_snapshot(), args->channel_id);
+	msg = stasis_cache_get(caching_topic, ast_channel_snapshot(),
+			       args->channel_id);
 	if (!msg) {
-		fill_error(response, 404, "Not Found", "Channel not found");
+		stasis_http_response_error(
+			response, 404, "Not Found",
+			"Channel not found");
 		return;
 	}
 
 	snapshot = stasis_message_data(msg);
 	ast_assert(snapshot != NULL);
 
-	fill_ok(response, ast_channel_snapshot_to_json(snapshot));
+	stasis_http_response_ok(response,
+				ast_channel_snapshot_to_json(snapshot));
 }
 
 void stasis_http_delete_channel(struct ast_variable *headers,
@@ -196,40 +173,45 @@
 
 	chan = ast_channel_get_by_name(args->channel_id);
 	if (chan == NULL) {
-		fill_error(response, 404, "Not Found",
-			   "Channel not found");
+		stasis_http_response_error(
+			response, 404, "Not Found",
+			"Channel not found");
 		return;
 	}
 
 	ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
 
-	fill_no_content(response);
-}
-
-void stasis_http_get_channels(struct ast_variable *headers, struct ast_get_channels_args *args, struct stasis_http_response *response)
+	stasis_http_response_no_content(response);
+}
+
+void stasis_http_get_channels(struct ast_variable *headers,
+			      struct ast_get_channels_args *args,
+			      struct stasis_http_response *response)
 {
 	RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
 	RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
 	struct ao2_iterator i;
 	void *obj;
 
 	caching_topic = ast_channel_topic_all_cached();
 	if (!caching_topic) {
-		fill_error(response, 500, "Internal Server Error", "Message bus not initialized");
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Message bus not initialized");
 		return;
 	}
 	ao2_ref(caching_topic, +1);
 
 	snapshots = stasis_cache_dump(caching_topic, ast_channel_snapshot());
 	if (!snapshots) {
-		fill_error(response, 500, "Internal Server Error", "Allocation failed");
-		return;
-	}
-
-	message = ast_json_array_create();
-	if (!message) {
-		fill_error(response, 500, "Internal Server Error", "Allocation failed");
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	json = ast_json_array_create();
+	if (!json) {
+		stasis_http_response_alloc_failed(response);
 		return;
 	}
 
@@ -237,17 +219,21 @@
 	while ((obj = ao2_iterator_next(&i))) {
 		RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
 		struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
-		if (ast_json_array_append(message, ast_channel_snapshot_to_json(snapshot))) {
-			fill_error(response, 500, "Internal Server Error", "Allocation failed");
+		int r = ast_json_array_append(
+			json, ast_channel_snapshot_to_json(snapshot));
+		if (r != 0) {
+			stasis_http_response_alloc_failed(response);
 			return;
 		}
 	}
 	ao2_iterator_destroy(&i);
 
-	fill_ok(response, ast_json_ref(message));
-}
-
-void stasis_http_originate(struct ast_variable *headers, struct ast_originate_args *args, struct stasis_http_response *response)
+	stasis_http_response_ok(response, ast_json_ref(json));
+}
+
+void stasis_http_originate(struct ast_variable *headers,
+			   struct ast_originate_args *args,
+			   struct stasis_http_response *response)
 {
 	if (args->endpoint) {
 		ast_log(LOG_DEBUG, "Dialing specific endpoint %s\n", args->endpoint);




More information about the asterisk-commits mailing list