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 */
|
/* UPGRADE */
|
||||||
bool is_upgrade;
|
bool is_upgrade;
|
||||||
|
/* PASSTHROUGH */
|
||||||
|
bool is_passthrough;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short major, short minor);
|
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 */
|
/* 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)
|
if (ret == -1)
|
||||||
{
|
{
|
||||||
TFE_STREAM_LOG_ERROR(stream, "Failed at parsing stream as HTTP: %u, %s, %s",
|
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;
|
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 */
|
/* Some kind of error happened, write log and detach the stream */
|
||||||
if (ret == -1)
|
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 */
|
/* accept-encoding, host is located in header's K-V structure */
|
||||||
hf_req_spec->method = (enum tfe_http_std_method) parser->method;
|
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};
|
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);
|
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);
|
__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;
|
tfe_http_event event = (hf_direction == TFE_HTTP_REQUEST) ? EV_HTTP_REQ_HDR : EV_HTTP_RESP_HDR;
|
||||||
if (hf_private->event_cb)
|
if (hf_private->event_cb)
|
||||||
{
|
{
|
||||||
@@ -1095,9 +1107,14 @@ void __write_access_log(struct http_session_private * hs_private)
|
|||||||
/* Upgrade Tag */
|
/* Upgrade Tag */
|
||||||
const char * __str_upgrade = response ? response->is_upgrade ? "UPGRADE" : "-" : "-";
|
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;
|
char * __access_log;
|
||||||
asprintf(&__access_log, "%d %s %s HTTP/%d.%d %s %s %s %s", hs_private->hs_public.session_id, __str_method,
|
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_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;
|
const struct tfe_stream * stream = hs_private->hc_private->stream;
|
||||||
tfe_stream_write_access_log(stream, RLOG_LV_INFO, "%s", __access_log);
|
tfe_stream_write_access_log(stream, RLOG_LV_INFO, "%s", __access_log);
|
||||||
|
|||||||
Reference in New Issue
Block a user