diff options
Diffstat (limited to 'src/plugins/http/http.c')
-rw-r--r-- | src/plugins/http/http.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c index a32f6f6cb84..d01ee7f0fc6 100644 --- a/src/plugins/http/http.c +++ b/src/plugins/http/http.c @@ -527,13 +527,18 @@ v_find_index (u8 *vec, u32 offset, u32 num, char *str) static void http_identify_optional_query (http_conn_t *hc) { - u32 pos = vec_search (hc->rx_buf, '?'); - if (~0 != pos) + int i; + for (i = hc->target_path_offset; + i < (hc->target_path_offset + hc->target_path_len); i++) { - hc->target_query_offset = pos + 1; - hc->target_query_len = - hc->target_path_offset + hc->target_path_len - hc->target_query_offset; - hc->target_path_len = hc->target_path_len - hc->target_query_len - 1; + if (hc->rx_buf[i] == '?') + { + hc->target_query_offset = i + 1; + hc->target_query_len = hc->target_path_offset + hc->target_path_len - + hc->target_query_offset; + hc->target_path_len = hc->target_path_len - hc->target_query_len - 1; + break; + } } } @@ -674,7 +679,9 @@ http_parse_request_line (http_conn_t *hc, http_status_code_t *ec) } /* parse request-target */ + HTTP_DBG (0, "http at %d", i); target_len = i - hc->target_path_offset; + HTTP_DBG (0, "target_len %d", target_len); if (target_len < 1) { clib_warning ("request-target not present"); @@ -911,7 +918,7 @@ http_state_wait_server_reply (http_conn_t *hc, transport_send_params_t *sp) http_msg_t msg = {}; app_worker_t *app_wrk; session_t *as; - u32 len, max_enq; + u32 len, max_enq, body_sent; http_status_code_t ec; http_main_t *hm = &http_main; @@ -972,16 +979,16 @@ http_state_wait_server_reply (http_conn_t *hc, transport_send_params_t *sp) http_read_message_drop (hc, len); - if (hc->body_len == 0) + body_sent = len - hc->control_data_len; + hc->to_recv = hc->body_len - body_sent; + if (hc->to_recv == 0) { - /* no response body, we are done */ - hc->to_recv = 0; + /* all sent, we are done */ http_state_change (hc, HTTP_STATE_WAIT_APP_METHOD); } else { - /* stream response body */ - hc->to_recv = hc->body_len; + /* stream rest of the response body */ http_state_change (hc, HTTP_STATE_CLIENT_IO_MORE_DATA); } @@ -1006,7 +1013,7 @@ http_state_wait_client_method (http_conn_t *hc, transport_send_params_t *sp) http_msg_t msg; session_t *as; int rv; - u32 len, max_enq; + u32 len, max_enq, max_deq, body_sent; rv = http_read_message (hc); @@ -1034,16 +1041,20 @@ http_state_wait_client_method (http_conn_t *hc, transport_send_params_t *sp) if (rv) goto error; - /* send "control data" and request body */ + /* send at least "control data" which is necessary minimum, + * if there is some space send also portion of body */ as = session_get_from_handle (hc->h_pa_session_handle); - len = hc->control_data_len + hc->body_len; max_enq = svm_fifo_max_enqueue (as->rx_fifo); - if (max_enq < len) + if (max_enq < hc->control_data_len) { - /* TODO stream body of large POST */ - clib_warning ("not enough room for data in app's rx fifo"); + clib_warning ("not enough room for control data in app's rx fifo"); + ec = HTTP_STATUS_INTERNAL_ERROR; goto error; } + /* do not dequeue more than one HTTP request, we do not support pipelining */ + max_deq = + clib_min (hc->control_data_len + hc->body_len, vec_len (hc->rx_buf)); + len = clib_min (max_enq, max_deq); msg.type = HTTP_MSG_REQUEST; msg.method_type = hc->method; @@ -1065,9 +1076,21 @@ http_state_wait_client_method (http_conn_t *hc, transport_send_params_t *sp) rv = svm_fifo_enqueue_segments (as->rx_fifo, segs, 2, 0 /* allow partial */); ASSERT (rv == (sizeof (msg) + len)); - /* drop everything, we do not support pipelining */ - http_read_message_drop_all (hc); - http_state_change (hc, HTTP_STATE_WAIT_APP_REPLY); + body_sent = len - hc->control_data_len; + hc->to_recv = hc->body_len - body_sent; + if (hc->to_recv == 0) + { + /* drop everything, we do not support pipelining */ + http_read_message_drop_all (hc); + /* all sent, we are done */ + http_state_change (hc, HTTP_STATE_WAIT_APP_REPLY); + } + else + { + http_read_message_drop (hc, len); + /* stream rest of the response body */ + http_state_change (hc, HTTP_STATE_CLIENT_IO_MORE_DATA); + } app_wrk = app_worker_get_if_valid (as->app_wrk_index); if (app_wrk) @@ -1408,8 +1431,12 @@ http_state_client_io_more_data (http_conn_t *hc, transport_send_params_t *sp) hc->to_recv -= rv; HTTP_DBG (1, "drained %d from ts; remains %d", rv, hc->to_recv); + /* Finished transaction: + * server back to HTTP_STATE_WAIT_APP_REPLY + * client to HTTP_STATE_WAIT_APP_METHOD */ if (hc->to_recv == 0) - http_state_change (hc, HTTP_STATE_WAIT_APP_METHOD); + http_state_change (hc, hc->is_server ? HTTP_STATE_WAIT_APP_REPLY : + HTTP_STATE_WAIT_APP_METHOD); app_wrk = app_worker_get_if_valid (as->app_wrk_index); if (app_wrk) |