From: Semir Sionek Date: Tue, 3 Jun 2025 15:07:28 +0000 (+0000) Subject: hsa: in http client print the response body only for text/* X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F72%2F43072%2F16;p=vpp.git hsa: in http client print the response body only for text/* Type: improvement Change-Id: I9a2e6b9344b64018b0c6872dbd051d7c39c7a0c3 Signed-off-by: Semir Sionek --- diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index 8b69072a608..88cb8863f18 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -38,7 +38,7 @@ func init() { HttpRequestLineTest, HttpClientGetTimeout, HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest, HttpClientGetRepeatTest, HttpClientPostRepeatTest, HttpIgnoreH2UpgradeTest, HttpInvalidAuthorityFormUriTest, HttpHeaderErrorConnectionDropTest, HttpClientInvalidHeaderNameTest, HttpStaticHttp1OnlyTest, HttpTimerSessionDisable, HttpClientBodySizeTest, - HttpStaticRedirectTest) + HttpStaticRedirectTest, HttpClientNoPrintTest) RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest, PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest, PromConsecutiveConnectionsTest, HttpGetTpsTlsTest, HttpPostTpsTlsTest) @@ -459,6 +459,30 @@ func HttpClientPostFormTest(s *NoTopoSuite) { s.AssertContains(o, "200 OK") } +func HttpClientNoPrintTest(s *NoTopoSuite) { + serverAddress := s.HostAddr() + ":" + s.Ports.Http + server := ghttp.NewUnstartedServer() + l, err := net.Listen("tcp", serverAddress) + s.AssertNil(err, fmt.Sprint(err)) + server.HTTPTestServer.Listener = l + server.AppendHandlers( + ghttp.CombineHandlers( + s.LogHttpReq(true), + ghttp.VerifyRequest("GET", "/"), + // Bogus header just for testing + ghttp.RespondWith(http.StatusOK, "

Hello

", http.Header{"Content-Type": {"image/jpeg"}}), + )) + server.Start() + defer server.Close() + uri := "http://" + serverAddress + vpp := s.Containers.Vpp.VppInstance + o := vpp.Vppctl("http client verbose uri " + uri) + + s.Log(o) + s.AssertContains(o, "* binary file, not printing!", "no warning message found!") + s.AssertNotContains(o, "", " found in the result!") +} + func HttpClientGetResponseBodyTest(s *NoTopoSuite) { response := "hello world" size := len(response) diff --git a/src/plugins/hs_apps/http_client.c b/src/plugins/hs_apps/http_client.c index 7b86278d440..5787b4566bf 100644 --- a/src/plugins/hs_apps/http_client.c +++ b/src/plugins/hs_apps/http_client.c @@ -6,10 +6,23 @@ #include #include #include +#include #include #include #include +#define foreach_hc_s_flag \ + _ (1, IS_CLOSED) \ + _ (2, PRINTABLE_BODY) \ + _ (4, BODY_OVER_LIMIT) + +typedef enum hc_s_flag_ +{ +#define _(n, s) HC_S_FLAG_##s = n, + foreach_hc_s_flag +#undef _ +} hc_s_flags; + typedef struct { u64 req_per_wrk; @@ -24,8 +37,7 @@ typedef struct u32 session_index; clib_thread_index_t thread_index; u64 to_recv; - u8 is_closed; - u8 body_over_limit; + u8 session_flags; hc_stats_t stats; u64 data_offset; u64 body_recv; @@ -98,6 +110,19 @@ typedef enum HC_REPEAT_DONE, } hc_cli_signal_t; +#define mime_printable_max_len 35 +const char mime_printable[][mime_printable_max_len] = { + "text/\0", + "application/json\0", + "application/javascript\0", + "application/x-yaml\0", + "application/x-www-form-urlencoded\0", + "application/xml\0", + "application/x-sh\0", + "application/x-tex\0", + "application/x-javascript\0", + "application/x-powershell\0" +}; static hc_main_t hc_main; static hc_stats_t hc_stats; @@ -350,7 +375,7 @@ hc_session_reset_callback (session_t *s) int rv; hc_session = hc_session_get (s->opaque, s->thread_index); - hc_session->is_closed = 1; + hc_session->session_flags |= HC_S_FLAG_IS_CLOSED; a->handle = session_handle (s); a->app_index = hcm->app_index; @@ -371,7 +396,7 @@ hc_rx_callback (session_t *s) session_error_t session_err = 0; int send_err = 0; - if (hc_session->is_closed) + if (hc_session->session_flags & HC_S_FLAG_IS_CLOSED) { clib_warning ("hc_session_index[%d] is closed", s->opaque); return -1; @@ -401,17 +426,43 @@ hc_rx_callback (session_t *s) hc_session->response_status = format (0, "%U", format_http_status_code, msg.code); + http_header_table_t ht = HTTP_HEADER_TABLE_NULL; + svm_fifo_dequeue_drop (s->rx_fifo, msg.data.headers_offset); vec_validate (hc_session->resp_headers, msg.data.headers_len - 1); vec_set_len (hc_session->resp_headers, msg.data.headers_len); rv = svm_fifo_dequeue (s->rx_fifo, msg.data.headers_len, hc_session->resp_headers); + ht.buf = hc_session->resp_headers; ASSERT (rv == msg.data.headers_len); HTTP_DBG (1, (char *) format (0, "%v", hc_session->resp_headers)); msg.data.body_offset -= msg.data.headers_len + msg.data.headers_offset; + + http_build_header_table (&ht, msg); + const http_token_t *content_type = http_get_header ( + &ht, http_header_name_token (HTTP_HEADER_CONTENT_TYPE)); + if (content_type) + { + for (u8 i = 0; i < sizeof (mime_printable) / + (sizeof (char) * mime_printable_max_len); + i++) + { + u8 mime_len = + clib_strnlen (mime_printable[i], mime_printable_max_len); + if (content_type->len >= mime_len && + clib_strncmp (content_type->base, mime_printable[i], + mime_len) == 0) + { + hc_session->session_flags |= HC_S_FLAG_PRINTABLE_BODY; + break; + } + } + } + ht.buf = NULL; + http_free_header_table (&ht); } if (msg.data.body_len == 0) @@ -428,10 +479,11 @@ hc_rx_callback (session_t *s) goto done; } if (msg.data.body_len > hcm->max_body_size) - hc_session->body_over_limit = true; + hc_session->session_flags |= HC_S_FLAG_BODY_OVER_LIMIT; vec_validate (hc_session->http_response, - (hc_session->body_over_limit ? hcm->rx_fifo_size - 1 : - msg.data.body_len - 1)); + (hc_session->session_flags & HC_S_FLAG_BODY_OVER_LIMIT ? + hcm->rx_fifo_size - 1 : + msg.data.body_len - 1)); vec_reset_length (hc_session->http_response); } @@ -454,7 +506,7 @@ hc_rx_callback (session_t *s) } ASSERT (rv == n_deq); - if (!hc_session->body_over_limit) + if (!(hc_session->session_flags & HC_S_FLAG_BODY_OVER_LIMIT)) vec_set_len (hc_session->http_response, curr + n_deq); ASSERT (hc_session->to_recv >= rv); hc_session->to_recv -= rv; @@ -732,14 +784,21 @@ hc_get_event (vlib_main_t *vm) { wrk = hc_worker_get (hcm->worker_index); hc_session = hc_session_get (wrk->session_index, wrk->thread_index); - vlib_cli_output (vm, "< %v\n< %v\n", hc_session->response_status, + vlib_cli_output (vm, "< %v\n< %v\n%v", hc_session->response_status, hc_session->resp_headers); - if (hc_session->body_over_limit) + if (hc_session->session_flags & HC_S_FLAG_BODY_OVER_LIMIT) vlib_cli_output ( vm, "* message body over limit, read total %llu bytes", hc_session->body_recv); else - vlib_cli_output (vm, "%v", hc_session->http_response); + { + if (hc_session->session_flags & HC_S_FLAG_PRINTABLE_BODY) + vlib_cli_output (vm, "%v", hc_session->http_response); + else + vlib_cli_output (vm, + "* binary file, not printing!\n* consider " + "saving to file with the 'file' option"); + } } break; case HC_REPEAT_DONE: