修正HTTP应答构建时缺少Content-Encoding和Content-Length的缺陷。
This commit is contained in:
@@ -92,6 +92,19 @@ uint16_t __hf_content_encoding_parse(const char * str_content_encoding)
|
|||||||
return HTTP_ACCEPT_ENCODING_NONE;
|
return HTTP_ACCEPT_ENCODING_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char * __hf_content_encoding_to_str(unsigned int encode)
|
||||||
|
{
|
||||||
|
switch (encode)
|
||||||
|
{
|
||||||
|
case HTTP_ACCEPT_ENCODING_GZIP: return "gzip";
|
||||||
|
case HTTP_ACCEPT_ENCODING_X_GZIP: return "x-gzip";
|
||||||
|
case HTTP_ACCEPT_ENCODING_DEFLATE: return "deflate";
|
||||||
|
case HTTP_ACCEPT_ENCODING_BZIP2: return "bzip2";
|
||||||
|
case HTTP_ACCEPT_ENCODING_X_BZIP2: return "x-bzip2";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* To flush header field and value which stash in evbuffer */
|
/* To flush header field and value which stash in evbuffer */
|
||||||
static void __http_half_header_kv_complete(struct http_half_private * hf_private)
|
static void __http_half_header_kv_complete(struct http_half_private * hf_private)
|
||||||
{
|
{
|
||||||
@@ -444,16 +457,36 @@ const char * hf_ops_field_read(const struct tfe_http_half * half, const struct h
|
|||||||
return __header_found != NULL ? __header_iter->value : NULL;
|
return __header_found != NULL ? __header_iter->value : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hf_ops_field_write(struct tfe_http_half * half, const struct http_field_name * name, const char * value)
|
int hf_ops_field_write(struct tfe_http_half * half, const struct http_field_name * field, const char * value)
|
||||||
{
|
{
|
||||||
struct http_half_private * hf_private = to_hf_private(half);
|
struct http_half_private * hf_private = to_hf_private(half);
|
||||||
assert(hf_private->major == 0 || hf_private->major == 1);
|
assert(hf_private->major == 0 || hf_private->major == 1);
|
||||||
|
|
||||||
struct http_header_private * __header = ALLOC(struct http_header_private, 1);
|
struct http_header_private * __header_iter = NULL;
|
||||||
__header->field = http_field_name_duplicate(name);
|
struct http_header_private * __header_found = NULL;
|
||||||
__header->value = tfe_strdup(value);
|
|
||||||
|
TAILQ_FOREACH(__header_iter, &hf_private->header_list, next)
|
||||||
|
{
|
||||||
|
if (http_field_name_compare(__header_iter->field, field) != 0) continue;
|
||||||
|
__header_found = __header_iter; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Found a header, update a value,
|
||||||
|
* or insert a new header k-v in the tail of the header list */
|
||||||
|
|
||||||
|
if(__header_found != NULL)
|
||||||
|
{
|
||||||
|
if (__header_found->value != NULL) free(__header_found->value);
|
||||||
|
__header_found->value = tfe_strdup(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct http_header_private * __header = ALLOC(struct http_header_private, 1);
|
||||||
|
__header->field = http_field_name_duplicate(field);
|
||||||
|
__header->value = tfe_strdup(value);
|
||||||
|
TAILQ_INSERT_TAIL(&hf_private->header_list, __header, next);
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&hf_private->header_list, __header, next);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,6 +819,30 @@ void hf_private_construct(struct http_half_private * hf_private)
|
|||||||
evbuffer_drain(hf_private->evbuf_raw, __buf_length);
|
evbuffer_drain(hf_private->evbuf_raw, __buf_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Terminal the end of gzip stream */
|
||||||
|
if (hf_private->evbuf_body && hf_private->cv_compress_object)
|
||||||
|
{
|
||||||
|
hf_content_compress_write(hf_private->cv_compress_object, NULL, 0, hf_private->evbuf_body, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hf_private->content_encoding != HTTP_ACCEPT_ENCODING_NONE)
|
||||||
|
{
|
||||||
|
const char * __str_content_encoding = __hf_content_encoding_to_str(hf_private->content_encoding);
|
||||||
|
const static struct http_field_name __cont_encoding_type_name = {TFE_HTTP_CONT_ENCODING, NULL};
|
||||||
|
tfe_http_field_write(hf_public, &__cont_encoding_type_name, __str_content_encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* have body, write content-length and content-type */
|
||||||
|
if (hf_private->evbuf_body)
|
||||||
|
{
|
||||||
|
/* To string */
|
||||||
|
char str_sz_evbuf_body[TFE_STRING_MAX];
|
||||||
|
snprintf(str_sz_evbuf_body, sizeof(str_sz_evbuf_body) - 1, "%lu", evbuffer_get_length(hf_private->evbuf_body));
|
||||||
|
|
||||||
|
const static struct http_field_name __cont_encoding_length_name = {TFE_HTTP_CONT_LENGTH, NULL};
|
||||||
|
tfe_http_field_write(hf_public, &__cont_encoding_length_name, str_sz_evbuf_body);
|
||||||
|
}
|
||||||
|
|
||||||
/* HTTP Request/Response first line */
|
/* HTTP Request/Response first line */
|
||||||
if (hf_public->direction == TFE_HTTP_REQUEST) __construct_request_line(hf_private);
|
if (hf_public->direction == TFE_HTTP_REQUEST) __construct_request_line(hf_private);
|
||||||
else __construct_response_line(hf_private);
|
else __construct_response_line(hf_private);
|
||||||
@@ -804,12 +861,6 @@ void hf_private_construct(struct http_half_private * hf_private)
|
|||||||
/* delimitor between header and body */
|
/* delimitor between header and body */
|
||||||
evbuffer_add_printf(hf_private->evbuf_raw, "\r\n");
|
evbuffer_add_printf(hf_private->evbuf_raw, "\r\n");
|
||||||
|
|
||||||
/* Terminal the end of gzip stream */
|
|
||||||
if (hf_private->evbuf_body && hf_private->cv_compress_object)
|
|
||||||
{
|
|
||||||
hf_content_compress_write(hf_private->cv_compress_object, NULL, 0, hf_private->evbuf_body, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add body */
|
/* add body */
|
||||||
if (hf_private->evbuf_body)
|
if (hf_private->evbuf_body)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user