Close #60 修正POST请求无Content-Length字段时无法转发请求的问题
* 部分HTTP POST请求中无有Content-Length字段,导致无法确定请求的边界。 * 现修正为,当发现Content-Length字段缺失时,Passthrough整个TCP连接。 * TODO: 解析POST编码或回应411应答。
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user