修正HTTP解析层处理HTTP-Header的错误流程
* 原流程在解析同一个Field-Value对时,无法正确处理Header多次调用拼成完整字符串的情况,现修正; * 原流程在处理Field-Value底层Buffer时计算长度有误,导致清空buffer时剩余最后的'\0',现修正。
This commit is contained in:
@@ -84,6 +84,8 @@ static void __http_half_header_kv_complete(struct http_half_private * hf_private
|
||||
/* Write a '\0' for evbuffers */
|
||||
evbuffer_add(hf_private->evbuf_header_field, &__zero, sizeof(__zero));
|
||||
evbuffer_add(hf_private->evbuf_header_value, &__zero, sizeof(__zero));
|
||||
sz_evbuf_field = evbuffer_get_length(hf_private->evbuf_header_field);
|
||||
sz_evbuf_value = evbuffer_get_length(hf_private->evbuf_header_value);
|
||||
|
||||
/* Convert evbuffer to const char * pair */
|
||||
str_field = (const char *) evbuffer_pullup(hf_private->evbuf_header_field, sz_evbuf_field);
|
||||
@@ -107,6 +109,8 @@ static void __http_half_header_kv_complete(struct http_half_private * hf_private
|
||||
__clear_buffer:
|
||||
evbuffer_drain(hf_private->evbuf_header_field, sz_evbuf_field);
|
||||
evbuffer_drain(hf_private->evbuf_header_value, sz_evbuf_value);
|
||||
hf_private->is_evbuf_header_value_set = false;
|
||||
hf_private->is_evbuf_header_field_set = false;
|
||||
}
|
||||
|
||||
void __hf_public_req_fill_from_private(struct http_half_private * hf_private, struct http_parser * parser)
|
||||
@@ -117,10 +121,10 @@ 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;
|
||||
const static struct http_field_name __host_field_name =
|
||||
{
|
||||
.field_id = TFE_HTTP_HOST,
|
||||
.field_name = NULL
|
||||
};
|
||||
{
|
||||
.field_id = TFE_HTTP_HOST,
|
||||
.field_name = NULL
|
||||
};
|
||||
|
||||
hf_req_spec->host = (char *) tfe_http_field_read(hf_public, &__host_field_name);
|
||||
|
||||
@@ -131,7 +135,7 @@ void __hf_public_req_fill_from_private(struct http_half_private * hf_private, st
|
||||
|
||||
/* TODO: URL
|
||||
* url is more complex. need to review RFC */
|
||||
hf_req_spec->url = NULL;
|
||||
hf_req_spec->url = hf_req_spec->uri;
|
||||
}
|
||||
|
||||
void __hf_public_resp_fill_from_private(struct http_half_private * hf_private, struct http_parser * parser)
|
||||
@@ -142,10 +146,10 @@ void __hf_public_resp_fill_from_private(struct http_half_private * hf_private, s
|
||||
/* Status Code */
|
||||
hf_resp_spec->resp_code = parser->status_code;
|
||||
const static struct http_field_name __cont_encoding_field_name =
|
||||
{
|
||||
.field_id = TFE_HTTP_CONT_ENCODING,
|
||||
.field_name = NULL
|
||||
};
|
||||
{
|
||||
.field_id = TFE_HTTP_CONT_ENCODING,
|
||||
.field_name = NULL
|
||||
};
|
||||
|
||||
/* Content Encoding */
|
||||
hf_resp_spec->content_encoding = (char *) tfe_http_field_read(hf_public, &__cont_encoding_field_name);
|
||||
@@ -164,11 +168,13 @@ static int __parser_callback_on_message_begin(struct http_parser * parser)
|
||||
assert(hf_private->evbuf_uri == NULL && hf_private->evbuf_body == NULL);
|
||||
assert(hf_private->evbuf_header_field == NULL && hf_private->evbuf_header_value == NULL);
|
||||
|
||||
hf_private->evbuf_uri = evbuffer_new();
|
||||
hf_private->evbuf_header_field = evbuffer_new();
|
||||
hf_private->evbuf_header_value = evbuffer_new();
|
||||
hf_private->evbuf_body = evbuffer_new();
|
||||
hf_private->is_evbuf_header_field_set = false;
|
||||
hf_private->is_evbuf_header_value_set = false;
|
||||
|
||||
hf_private->evbuf_uri = evbuffer_new();
|
||||
hf_private->evbuf_body = evbuffer_new();
|
||||
hf_private->body_status = STATUS_INIT;
|
||||
hf_private->message_status = STATUS_READING;
|
||||
|
||||
@@ -186,19 +192,19 @@ static int __parser_callback_on_uri_field(struct http_parser * parser, const cha
|
||||
static int __parser_callback_on_header_field(struct http_parser * parser, const char * at, size_t length)
|
||||
{
|
||||
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser);
|
||||
|
||||
/* Last field-value tuple doesn't push into hf_private, flush these */
|
||||
if (evbuffer_get_length(hf_private->evbuf_header_field) != 0)
|
||||
if (hf_private->is_evbuf_header_field_set && hf_private->is_evbuf_header_value_set)
|
||||
{
|
||||
__http_half_header_kv_complete(hf_private);
|
||||
}
|
||||
|
||||
hf_private->is_evbuf_header_field_set = true;
|
||||
return evbuffer_add(hf_private->evbuf_header_field, at, length);
|
||||
}
|
||||
|
||||
static int __parser_callback_on_header_value(struct http_parser * parser, const char * at, size_t length)
|
||||
{
|
||||
struct http_half_private * hf_private = __PARSER_TO_HF_PRIVATE(parser);
|
||||
hf_private->is_evbuf_header_value_set = true;
|
||||
return evbuffer_add(hf_private->evbuf_header_value, at, length);
|
||||
}
|
||||
|
||||
@@ -429,6 +435,8 @@ struct http_half_private * hf_private_create(tfe_http_direction ht_dir, short ma
|
||||
|
||||
hf_private->parse_settings = &__http_half_parse_setting;
|
||||
hf_private->parse_object->data = hf_private;
|
||||
|
||||
TAILQ_INIT(&hf_private->header_list);
|
||||
return hf_private;
|
||||
}
|
||||
|
||||
@@ -440,6 +448,11 @@ void hf_private_set_callback(struct http_half_private * hf_private, hf_private_c
|
||||
hf_private->event_cb_user_deleter = user_deleter;
|
||||
}
|
||||
|
||||
void hf_private_set_session(struct http_half_private * hf_private, struct http_session_private * hs_private)
|
||||
{
|
||||
hf_private->session = hs_private;
|
||||
}
|
||||
|
||||
int hf_private_parse(struct http_half_private * hf_private, const unsigned char * data, size_t len)
|
||||
{
|
||||
assert(hf_private->parse_cursor <= len);
|
||||
|
||||
Reference in New Issue
Block a user