summaryrefslogtreecommitdiffstats
path: root/src/plugins/hs_apps/http_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/hs_apps/http_cli.c')
-rw-r--r--src/plugins/hs_apps/http_cli.c111
1 files changed, 85 insertions, 26 deletions
diff --git a/src/plugins/hs_apps/http_cli.c b/src/plugins/hs_apps/http_cli.c
index f42f65342c3..4970da72012 100644
--- a/src/plugins/hs_apps/http_cli.c
+++ b/src/plugins/hs_apps/http_cli.c
@@ -18,11 +18,20 @@
#include <vnet/session/session.h>
#include <http/http.h>
+#define HCS_DEBUG 0
+
+#if HCS_DEBUG
+#define HCS_DBG(_fmt, _args...) clib_warning (_fmt, ##_args)
+#else
+#define HCS_DBG(_fmt, _args...)
+#endif
+
typedef struct
{
u32 hs_index;
u32 thread_index;
u64 node_index;
+ u8 plain_text;
u8 *buf;
} hcs_cli_args_t;
@@ -139,7 +148,8 @@ hcs_cli_output (uword arg, u8 *buffer, uword buffer_bytes)
}
static void
-start_send_data (hcs_session_t *hs, http_status_code_t status)
+start_send_data (hcs_session_t *hs, http_status_code_t status,
+ http_content_type_t type)
{
http_msg_t msg;
session_t *ts;
@@ -147,7 +157,7 @@ start_send_data (hcs_session_t *hs, http_status_code_t status)
msg.type = HTTP_MSG_REPLY;
msg.code = status;
- msg.content_type = HTTP_CONTENT_TEXT_HTML;
+ msg.content_type = type;
msg.data.type = HTTP_MSG_DATA_INLINE;
msg.data.len = vec_len (hs->tx_buf);
@@ -181,6 +191,7 @@ send_data_to_http (void *rpc_args)
{
hcs_cli_args_t *args = (hcs_cli_args_t *) rpc_args;
hcs_session_t *hs;
+ http_content_type_t type = HTTP_CONTENT_TEXT_HTML;
hs = hcs_session_get (args->thread_index, args->hs_index);
if (!hs)
@@ -190,7 +201,9 @@ send_data_to_http (void *rpc_args)
}
hs->tx_buf = args->buf;
- start_send_data (hs, HTTP_STATUS_OK);
+ if (args->plain_text)
+ type = HTTP_CONTENT_TEXT_PLAIN;
+ start_send_data (hs, HTTP_STATUS_OK, type);
cleanup:
@@ -218,17 +231,9 @@ hcs_cli_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
{
if (request[i] == '/')
request[i] = ' ';
- else if (request[i] == ' ')
- {
- /* vlib_cli_input is vector-based, no need for a NULL */
- vec_set_len (request, i);
- break;
- }
i++;
}
-
- /* Generate the html header */
- html = format (0, html_header_template, request /* title */ );
+ HCS_DBG ("%v", request);
/* Run the command */
unformat_init_vector (&input, vec_dup (request));
@@ -236,9 +241,17 @@ hcs_cli_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
unformat_free (&input);
request = 0;
- /* Generate the html page */
- html = format (html, "%v", reply);
- html = format (html, html_footer);
+ if (args->plain_text)
+ {
+ html = format (0, "%v", reply);
+ }
+ else
+ {
+ /* Generate the html page */
+ html = format (0, html_header_template, request /* title */);
+ html = format (html, "%v", reply);
+ html = format (html, html_footer);
+ }
/* Send it */
rpc_args = clib_mem_alloc (sizeof (*args));
@@ -308,9 +321,10 @@ hcs_ts_rx_callback (session_t *ts)
hcs_cli_args_t args = {};
hcs_session_t *hs;
http_msg_t msg;
- int rv;
+ int rv, is_encoded = 0;
hs = hcs_session_get (ts->thread_index, ts->opaque);
+ hs->tx_buf = 0;
/* Read the http message header */
rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
@@ -318,23 +332,65 @@ hcs_ts_rx_callback (session_t *ts)
if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET)
{
- hs->tx_buf = 0;
- start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
- return 0;
+ start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED,
+ HTTP_CONTENT_TEXT_HTML);
+ goto done;
}
- if (msg.data.len == 0)
+ if (msg.data.target_path_len == 0 ||
+ msg.data.target_form != HTTP_TARGET_ORIGIN_FORM)
{
hs->tx_buf = 0;
- start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
- return 0;
+ start_send_data (hs, HTTP_STATUS_BAD_REQUEST, HTTP_CONTENT_TEXT_HTML);
+ goto done;
}
/* send the command to a new/recycled vlib process */
- vec_validate (args.buf, msg.data.len - 1);
- rv = svm_fifo_dequeue (ts->rx_fifo, msg.data.len, args.buf);
- ASSERT (rv == msg.data.len);
- vec_set_len (args.buf, rv);
+ vec_validate (args.buf, msg.data.target_path_len - 1);
+ rv = svm_fifo_peek (ts->rx_fifo, msg.data.target_path_offset,
+ msg.data.target_path_len, args.buf);
+ ASSERT (rv == msg.data.target_path_len);
+ HCS_DBG ("%v", args.buf);
+ if (http_validate_abs_path_syntax (args.buf, &is_encoded))
+ {
+ start_send_data (hs, HTTP_STATUS_BAD_REQUEST, HTTP_CONTENT_TEXT_HTML);
+ vec_free (args.buf);
+ goto done;
+ }
+ if (is_encoded)
+ {
+ u8 *decoded = http_percent_decode (args.buf);
+ vec_free (args.buf);
+ args.buf = decoded;
+ }
+
+ if (msg.data.headers_len)
+ {
+ u8 *headers = 0;
+ http_header_table_t *ht;
+ vec_validate (headers, msg.data.headers_len - 1);
+ rv = svm_fifo_peek (ts->rx_fifo, msg.data.headers_offset,
+ msg.data.headers_len, headers);
+ ASSERT (rv == msg.data.headers_len);
+ if (http_parse_headers (headers, &ht))
+ {
+ start_send_data (hs, HTTP_STATUS_BAD_REQUEST,
+ HTTP_CONTENT_TEXT_HTML);
+ vec_free (args.buf);
+ vec_free (headers);
+ goto done;
+ }
+ const char *accept_value = http_get_header (ht, HTTP_HEADER_ACCEPT);
+ if (accept_value)
+ {
+ HCS_DBG ("client accept: %s", accept_value);
+ /* just for testing purpose, we don't care about precedence */
+ if (strstr (accept_value, "text/plain"))
+ args.plain_text = 1;
+ }
+ http_free_header_table (ht);
+ vec_free (headers);
+ }
args.hs_index = hs->session_index;
args.thread_index = ts->thread_index;
@@ -345,6 +401,9 @@ hcs_ts_rx_callback (session_t *ts)
sizeof (args));
else
alloc_cli_process (&args);
+
+done:
+ svm_fifo_dequeue_drop (ts->rx_fifo, msg.data.len);
return 0;
}