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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Mar 12 16:32:53 CDT 2013


Author: dlee
Date: Tue Mar 12 16:32:49 2013
New Revision: 382975

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382975
Log:
Implement chanel hangup (delete).

The browser sends a CORS OPTIONS request, so this took a bit of coding.

Modified:
    team/dlee/stasis-http/include/asterisk/http.h
    team/dlee/stasis-http/include/asterisk/stasis_http.h
    team/dlee/stasis-http/main/http.c
    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/http.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/http.h?view=diff&rev=382975&r1=382974&r2=382975
==============================================================================
--- team/dlee/stasis-http/include/asterisk/http.h (original)
+++ team/dlee/stasis-http/include/asterisk/http.h Tue Mar 12 16:32:49 2013
@@ -60,6 +60,7 @@
 	AST_HTTP_HEAD,
 	AST_HTTP_PUT,
 	AST_HTTP_DELETE,
+	AST_HTTP_OPTIONS,
 	AST_HTTP_MAX_METHOD, /*!< Last entry in ast_http_method enum */
 };
 

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=382975&r1=382974&r2=382975
==============================================================================
--- team/dlee/stasis-http/include/asterisk/stasis_http.h (original)
+++ team/dlee/stasis-http/include/asterisk/stasis_http.h Tue Mar 12 16:32:49 2013
@@ -72,7 +72,10 @@
 struct stasis_http_response {
 	/*! Response message */
 	struct ast_json *message;
-	/*! HTTP response code. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */
+	/*! \r\n seperated response headers */
+	struct ast_str *headers;
+	/*! HTTP response code.
+	 * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html */
 	int response_code;
 	/*! Corresponding text for the response code */
 	const char *response_text; // Shouldn't http.c handle this?

Modified: team/dlee/stasis-http/main/http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/main/http.c?view=diff&rev=382975&r1=382974&r2=382975
==============================================================================
--- team/dlee/stasis-http/main/http.c (original)
+++ team/dlee/stasis-http/main/http.c Tue Mar 12 16:32:49 2013
@@ -154,6 +154,7 @@
 	{ AST_HTTP_HEAD,        "HEAD" },
 	{ AST_HTTP_PUT,         "PUT" },
 	{ AST_HTTP_DELETE,      "DELETE" },
+	{ AST_HTTP_OPTIONS,     "OPTIONS" },
 };
 
 const char *ast_get_http_method(enum ast_http_method method)
@@ -889,6 +890,8 @@
 		http_method = AST_HTTP_PUT;
 	} else if (!strcasecmp(method,"DELETE")) {
 		http_method = AST_HTTP_DELETE;
+	} else if (!strcasecmp(method,"OPTIONS")) {
+		http_method = AST_HTTP_OPTIONS;
 	}
 
 	uri = ast_skip_blanks(uri);	/* Skip white space */

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=382975&r1=382974&r2=382975
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_http.c (original)
+++ team/dlee/stasis-http/res/res_stasis_http.c Tue Mar 12 16:32:49 2013
@@ -118,6 +118,78 @@
 	response->response_text = "OK";
 }
 
+static void add_allow_header(struct stasis_rest_handlers *handler,
+			     struct stasis_http_response *response)
+{
+	enum ast_http_method m;
+	ast_str_append(&response->headers, 0,
+		       "Allow: OPTIONS");
+	for (m = 0; m < AST_HTTP_MAX_METHOD; ++m) {
+		if (handler->callbacks[m] != NULL) {
+			ast_str_append(&response->headers, 0,
+				       ",%s", ast_get_http_method(m));
+		}
+	}
+	ast_str_append(&response->headers, 0, "\r\n");
+}
+
+/*!
+ * \brief Handle OPTIONS request, mainly for CORS preflight requests.
+ *
+ * Some browsers will send this prior to non-simple methods (i.e. DELETE).
+ * See http://www.w3.org/TR/cors/ for the spec.
+ */
+static void handle_options(struct stasis_rest_handlers *handler,
+			   struct ast_variable *headers,
+			   struct stasis_http_response *response)
+{
+	char const *acr_method = NULL;
+	struct ast_variable *header;
+
+	for (header = headers; header != NULL; header = header->next) {
+		if (strcmp("Access-Control-Request-Method", header->name) == 0) {
+			acr_method = header->value;
+		}
+	}
+
+	if (acr_method != NULL) {
+		RAII_VAR(struct ast_str *, allow, NULL, ast_free);
+		enum ast_http_method m;
+		int allowed = 0;
+
+		allow = ast_str_create(20);
+
+		if (!allow) {
+			response_error(response, "Allocation failed", 500,
+				       "Internal Server Error");
+			return;
+		}
+
+		ast_str_append(&allow, 0,
+			       "Access-Control-Allow-Methods: OPTIONS");
+		for (m = 0; m < AST_HTTP_MAX_METHOD; ++m) {
+			if (handler->callbacks[m] != NULL) {
+				char const *m_str = ast_get_http_method(m);
+				if (strcmp(m_str, acr_method) == 0) {
+					allowed = 1;
+				}
+				ast_str_append(&allow, 0, ",%s", m_str);
+			}
+		}
+
+		if (allowed) {
+			ast_str_append(&response->headers, 0, "%s\r\n",
+				       ast_str_buffer(allow));
+		}
+	}
+	/* regular Allow header */
+	add_allow_header(handler, response);
+
+	response->response_code = 204;
+	response->response_text = "No Content";
+	response->message = NULL;
+}
+
 void stasis_http_invoke(const char *uri,
 			enum ast_http_method method,
 			struct ast_variable *get_params,
@@ -132,11 +204,6 @@
 	stasis_rest_callback callback;
 
 	ast_assert(handler != NULL);
-
-	if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
-		response_error(response, "Invalid method", 405, "Method Not Allowed");
-		return;
-	}
 
 	while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
 		struct stasis_rest_handlers *found_handler = NULL;
@@ -169,8 +236,20 @@
 	}
 
 	ast_assert(handler != NULL);
+	if (method == AST_HTTP_OPTIONS) {
+		handle_options(handler, headers, response);
+		return;
+	}
+
+	if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
+		add_allow_header(handler, response);
+		response_error(response, "Invalid method", 405, "Method Not Allowed");
+		return;
+	}
+
 	callback = handler->callbacks[method];
 	if (callback == NULL) {
+		add_allow_header(handler, response);
 		response_error(response, "Unsupported method", 405, "Method Not Allowed");
 		return;
 	}
@@ -296,21 +375,23 @@
 				struct ast_variable *get_params,
 				struct ast_variable *headers)
 {
-	RAII_VAR(struct ast_str *, http_headers, ast_str_create(40), ast_free);
+	RAII_VAR(struct ast_str *, response_headers, ast_str_create(40), ast_free);
 	RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
 	struct stasis_http_response response = {};
 	int ret = 0;
 
-	if (!http_headers || !response_body) {
+	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(&http_headers, 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));
@@ -332,32 +413,37 @@
 		}
 	}
 
+	/* Leaving message unset is only allowed for 204 (No Content).
+	 * If you explicitly want to have no content for a different return
+	 * code, set message to ast_json_null().
+	 */
 	ast_assert(response.response_code == 204 || response.message != NULL);
 	ast_assert(response.response_code > 0);
 
-	ast_str_append(&http_headers, 0, "Access-Control-Allow-Origin: *\r\n");
+	ast_str_append(&response_headers, 0, "Access-Control-Allow-Origin: *\r\n");
+	ast_str_append(&response_headers, 0, "%s", ast_str_buffer(response.headers));
 
 	/* response.message could be NULL, in which case the empty response_body
 	 * is correct
 	 */
-	if (response.message) {
-		ast_str_append(&http_headers, 0,
+	if (response.message && !ast_json_is_null(response.message)) {
+		ast_str_append(&response_headers, 0,
 			       "Content-type: application/json\r\n");
 		if (ast_json_dump_str(response.message, &response_body) != 0) {
 			/* Error encoding response */
 			response.response_code = 500;
 			response.response_text = "Internal Server Error";
 			ast_str_set(&response_body, 0, "%s", "");
-			ast_str_set(&http_headers, 0, "%s", "");
+			ast_str_set(&response_headers, 0, "%s", "");
 			ret = -1;
 		}
 	}
 
 	ast_http_send(ser, method, response.response_code,
-		      response.response_text, http_headers, response_body,
+		      response.response_text, response_headers, response_body,
 		      0, 0);
 	/* ast_http_send takes ownership, so we don't have to free them */
-	http_headers = NULL;
+	response_headers = NULL;
 	response_body = NULL;
 
 	ast_json_unref(response.message);

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=382975&r1=382974&r2=382975
==============================================================================
--- team/dlee/stasis-http/res/stasis_http/resource_channels.c (original)
+++ team/dlee/stasis-http/res/stasis_http/resource_channels.c Tue Mar 12 16:32:49 2013
@@ -86,7 +86,7 @@
 
 	ast_assert(response != NULL);
 
-	control = stasis_app_control_find_by_channel_id(ast_channel_uniqueid(chan));
+	control = stasis_app_control_find_by_channel_id(channel_id);
 	if (control == NULL) {
 		/* Distinguish between 404 and 409 errors */
 		RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
@@ -193,13 +193,12 @@
 				struct stasis_http_response *response)
 {
 	RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
-	int r;
-
-	chan = ast_channel_get_by_name(channel_id);
+
+	chan = ast_channel_get_by_name(args->channel_id);
 	if (chan == NULL) {
 		fill_error(response, 404, "Not Found",
 			   "Channel not found");
-		return NULL;
+		return;
 	}
 
 	ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);




More information about the asterisk-commits mailing list