[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