diff --git a/plugin/protocol/http/include/internal/http_half.h b/plugin/protocol/http/include/internal/http_half.h index fe762b9..86c8414 100644 --- a/plugin/protocol/http/include/internal/http_half.h +++ b/plugin/protocol/http/include/internal/http_half.h @@ -95,6 +95,8 @@ struct http_half_private /* UPGRADE */ bool is_upgrade; + /* PASSTHROUGH */ + bool is_passthrough; }; struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short major, short minor); diff --git a/plugin/protocol/http/src/http_entry.cpp b/plugin/protocol/http/src/http_entry.cpp index ccdcee4..8f42893 100644 --- a/plugin/protocol/http/src/http_entry.cpp +++ b/plugin/protocol/http/src/http_entry.cpp @@ -362,6 +362,11 @@ enum tfe_stream_action __http_connection_entry_on_request(const struct tfe_strea } /* Some kind of error happened, write log and detach the stream */ + if (ret == -1 && hf_private_req_in->is_passthrough) + { + goto __errout; + } + if (ret == -1) { TFE_STREAM_LOG_ERROR(stream, "Failed at parsing stream as HTTP: %u, %s, %s", @@ -475,6 +480,12 @@ enum tfe_stream_action __http_connection_entry_on_response(const struct tfe_stre return hf_private_resp_in->stream_action; } + /* Need to passthrough */ + if (ret == -1 && hf_private_resp_in->is_passthrough) + { + goto __errout; + } + /* Some kind of error happened, write log and detach the stream */ if (ret == -1) { diff --git a/plugin/protocol/http/src/http_half.cpp b/plugin/protocol/http/src/http_half.cpp index e2499af..a85374b 100644 --- a/plugin/protocol/http/src/http_half.cpp +++ b/plugin/protocol/http/src/http_half.cpp @@ -172,6 +172,8 @@ void __hf_public_req_fill_from_private(struct http_half_private * hf_private, st /* accept-encoding, host is located in header's K-V structure */ hf_req_spec->method = (enum tfe_http_std_method) parser->method; + hf_private->method_or_status = (enum tfe_http_std_method) parser->method; + const static struct http_field_name __host_field_name = {TFE_HTTP_HOST, NULL}; hf_req_spec->host = (char *) tfe_http_field_read(hf_public, &__host_field_name); @@ -320,6 +322,16 @@ static int __parser_callback_on_headers_complete(http_parser * parser) __hf_public_resp_fill_from_private(hf_private, parser); } + /* for POST, must contains 'content-length' */ + if (hf_direction == TFE_HTTP_REQUEST && hf_private->method_or_status == TFE_HTTP_METHOD_POST) + { + const static struct http_field_name __cont_encoding_field_name = {TFE_HTTP_CONT_LENGTH, NULL}; + char * __str_content_length = (char *) tfe_http_field_read(hf_public, &__cont_encoding_field_name); + + /* Does not contain a content-length, passthrough the whole TCP connection */ + if (unlikely(__str_content_length == NULL)) { hf_private->is_passthrough = true; return -1;} + } + tfe_http_event event = (hf_direction == TFE_HTTP_REQUEST) ? EV_HTTP_REQ_HDR : EV_HTTP_RESP_HDR; if (hf_private->event_cb) { @@ -334,8 +346,8 @@ static int __parser_callback_on_headers_complete(http_parser * parser) hf_private->stream_action = hf_private->user_stream_action; } - /* user's suspend tag is set, which indicate that the way to handle request/response - * cannot be determinate at now, need to defer */ + /* user's suspend tag is set, which indicate that the way to handle request/response + * cannot be determinate at now, need to defer */ else if (hs_private && hs_private->suspend_tag_user) { /* Pause parser, prevent to parse request/response body, @@ -1095,9 +1107,14 @@ void __write_access_log(struct http_session_private * hs_private) /* Upgrade Tag */ const char * __str_upgrade = response ? response->is_upgrade ? "UPGRADE" : "-" : "-"; + /* PASSTHROUGH */ + const char * __str_req_passthrough = request ? request->is_passthrough ? "PASS-THROUGH/REQ" : "-" : "-"; + const char * __str_resp_passthrough = response ? response->is_passthrough ? "PASS-THROUGH/REP" : "-" : "-"; + char * __access_log; - asprintf(&__access_log, "%d %s %s HTTP/%d.%d %s %s %s %s", hs_private->hs_public.session_id, __str_method, - __str_url, request->major, request->minor, __str_resp_code, __str_cont_type, __str_cont_encoding, __str_upgrade); + asprintf(&__access_log, "%d %s %s HTTP/%d.%d %s %s %s %s %s %s", hs_private->hs_public.session_id, __str_method, + __str_url, request->major, request->minor, __str_resp_code, __str_cont_type, __str_cont_encoding, + __str_upgrade, __str_req_passthrough, __str_resp_passthrough); const struct tfe_stream * stream = hs_private->hc_private->stream; tfe_stream_write_access_log(stream, RLOG_LV_INFO, "%s", __access_log);