mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-11 16:29:36 +00:00
MEDIUM: compression: don't compress when no data
This patch makes changes in the http_response_forward_body state machine. It checks if the compress algorithm had consumed data before swapping the temporary and the input buffer. So it prevents null sized zlib chunks.
This commit is contained in:
parent
b97b6190e1
commit
bf3ae61789
@ -34,7 +34,7 @@ int http_compression_buffer_add_data(struct session *s, struct buffer *in, struc
|
||||
int http_compression_buffer_end(struct session *s, struct buffer **in, struct buffer **out, int end);
|
||||
|
||||
int identity_init(struct comp_ctx *comp_ctx, int level);
|
||||
int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len);
|
||||
int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
|
||||
int identity_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
|
||||
int identity_reset(struct comp_ctx *comp_ctx);
|
||||
int identity_end(struct comp_ctx *comp_ctx);
|
||||
@ -43,17 +43,12 @@ int identity_end(struct comp_ctx *comp_ctx);
|
||||
#ifdef USE_ZLIB
|
||||
|
||||
int deflate_init(struct comp_ctx *comp_ctx, int level);
|
||||
int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len);
|
||||
int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
|
||||
int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
|
||||
int deflate_reset(struct comp_ctx *comp_ctx);
|
||||
int deflate_end(struct comp_ctx *comp_ctx);
|
||||
|
||||
int gzip_init(struct comp_ctx *comp_ctx, int level);
|
||||
int gzip_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len);
|
||||
int gzip_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
|
||||
int gzip_reset(struct comp_ctx *comp_ctx);
|
||||
int gzip_end(struct comp_ctx *comp_ctx);
|
||||
|
||||
#endif /* USE_ZLIB */
|
||||
|
||||
#endif /* _PROTO_COMP_H */
|
||||
|
@ -51,7 +51,7 @@ struct comp_algo {
|
||||
char *name;
|
||||
int name_len;
|
||||
int (*init)(struct comp_ctx *comp_ctx, int level);
|
||||
int (*add_data)(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len);
|
||||
int (*add_data)(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
|
||||
int (*flush)(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
|
||||
int (*reset)(struct comp_ctx *comp_ctx);
|
||||
int (*end)(struct comp_ctx *comp_ctx);
|
||||
|
@ -164,6 +164,7 @@ int http_compression_buffer_init(struct session *s, struct buffer *in, struct bu
|
||||
int http_compression_buffer_add_data(struct session *s, struct buffer *in, struct buffer *out)
|
||||
{
|
||||
struct http_msg *msg = &s->txn.rsp;
|
||||
int consumed_data = 0;
|
||||
int data_process_len;
|
||||
int left;
|
||||
int ret;
|
||||
@ -186,28 +187,23 @@ int http_compression_buffer_add_data(struct session *s, struct buffer *in, struc
|
||||
|
||||
left = data_process_len - bi_contig_data(in);
|
||||
if (left <= 0) {
|
||||
ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in),
|
||||
data_process_len, bi_end(out),
|
||||
out->size - buffer_len(out));
|
||||
consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in), data_process_len, out);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
out->i += ret;
|
||||
|
||||
} else {
|
||||
ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in), bi_contig_data(in), bi_end(out), out->size - buffer_len(out));
|
||||
consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, bi_ptr(in), bi_contig_data(in), out);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
out->i += ret;
|
||||
ret = s->comp_algo->add_data(&s->comp_ctx, in->data, left, bi_end(out), out->size - buffer_len(out));
|
||||
consumed_data += ret = s->comp_algo->add_data(&s->comp_ctx, in->data, left, out);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
out->i += ret;
|
||||
}
|
||||
|
||||
b_adv(in, data_process_len);
|
||||
msg->chunk_len -= data_process_len;
|
||||
|
||||
return 0;
|
||||
return consumed_data;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -309,15 +305,20 @@ int identity_init(struct comp_ctx *comp_ctx, int level)
|
||||
|
||||
/*
|
||||
* Process data
|
||||
* Return size of processed data or -1 on error
|
||||
* Return size of consumed data or -1 on error
|
||||
*/
|
||||
int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len)
|
||||
int identity_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
|
||||
{
|
||||
char *out_data = bi_end(out);
|
||||
int out_len = out->size - buffer_len(out);
|
||||
|
||||
if (out_len < in_len)
|
||||
return -1;
|
||||
|
||||
memcpy(out_data, in_data, in_len);
|
||||
|
||||
out->i += in_len;
|
||||
|
||||
return in_len;
|
||||
}
|
||||
|
||||
@ -462,10 +463,13 @@ int deflate_init(struct comp_ctx *comp_ctx, int level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, char *out_data, int out_len)
|
||||
/* Return the size of consumed data or -1 */
|
||||
int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out)
|
||||
{
|
||||
z_stream *strm = &comp_ctx->strm;
|
||||
int ret;
|
||||
z_stream *strm = &comp_ctx->strm;
|
||||
char *out_data = bi_end(out);
|
||||
int out_len = out->size - buffer_len(out);
|
||||
|
||||
if (in_len <= 0)
|
||||
return 0;
|
||||
@ -484,8 +488,9 @@ int deflate_add_data(struct comp_ctx *comp_ctx, const char *in_data, int in_len,
|
||||
return -1;
|
||||
|
||||
/* deflate update the available data out */
|
||||
out->i += out_len - strm->avail_out;
|
||||
|
||||
return out_len - strm->avail_out;
|
||||
return in_len - strm->avail_in;
|
||||
}
|
||||
|
||||
int deflate_flush(struct comp_ctx *comp_ctx, struct buffer *out, int flag)
|
||||
|
@ -5546,6 +5546,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi
|
||||
unsigned int bytes;
|
||||
static struct buffer *tmpbuf = NULL;
|
||||
int compressing = 0;
|
||||
int consumed_data = 0;
|
||||
|
||||
if (unlikely(msg->msg_state < HTTP_MSG_BODY))
|
||||
return 0;
|
||||
@ -5606,18 +5607,28 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi
|
||||
}
|
||||
|
||||
if (msg->msg_state == HTTP_MSG_DATA) {
|
||||
int ret;
|
||||
|
||||
/* must still forward */
|
||||
if (compressing)
|
||||
http_compression_buffer_add_data(s, res->buf, tmpbuf);
|
||||
if (compressing) {
|
||||
consumed_data += ret = http_compression_buffer_add_data(s, res->buf, tmpbuf);
|
||||
if (ret < 0)
|
||||
goto aborted_xfer;
|
||||
}
|
||||
|
||||
if (res->to_forward || msg->chunk_len)
|
||||
goto missing_data;
|
||||
|
||||
/* nothing left to forward */
|
||||
if (msg->flags & HTTP_MSGF_TE_CHNK)
|
||||
if (msg->flags & HTTP_MSGF_TE_CHNK) {
|
||||
msg->msg_state = HTTP_MSG_CHUNK_CRLF;
|
||||
else
|
||||
} else {
|
||||
msg->msg_state = HTTP_MSG_DONE;
|
||||
if (compressing && consumed_data) {
|
||||
http_compression_buffer_end(s, &res->buf, &tmpbuf, 1);
|
||||
compressing = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (msg->msg_state == HTTP_MSG_CHUNK_SIZE) {
|
||||
/* read the chunk size and assign it to ->chunk_len, then
|
||||
@ -5633,14 +5644,21 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi
|
||||
http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_CHUNK_SIZE, s->fe);
|
||||
goto return_bad_res;
|
||||
}
|
||||
/* skipping data if we are in compression mode */
|
||||
if (compressing && msg->chunk_len > 0) {
|
||||
b_adv(res->buf, msg->next);
|
||||
msg->next = 0;
|
||||
msg->sov = 0;
|
||||
msg->sol = 0;
|
||||
if (compressing) {
|
||||
if (likely(msg->chunk_len > 0)) {
|
||||
/* skipping data if we are in compression mode */
|
||||
b_adv(res->buf, msg->next);
|
||||
msg->next = 0;
|
||||
msg->sov = 0;
|
||||
msg->sol = 0;
|
||||
} else {
|
||||
if (consumed_data) {
|
||||
http_compression_buffer_end(s, &res->buf, &tmpbuf, 1);
|
||||
compressing = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* otherwise we're in HTTP_MSG_DATA or HTTP_MSG_TRAILERS state */
|
||||
/* otherwise we're in HTTP_MSG_DATA or HTTP_MSG_TRAILERS state */
|
||||
}
|
||||
else if (msg->msg_state == HTTP_MSG_CHUNK_CRLF) {
|
||||
/* we want the CRLF after the data */
|
||||
@ -5672,20 +5690,10 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi
|
||||
http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_TRAILERS, s->fe);
|
||||
goto return_bad_res;
|
||||
}
|
||||
if (compressing) {
|
||||
http_compression_buffer_end(s, &res->buf, &tmpbuf, 1);
|
||||
compressing = 0;
|
||||
}
|
||||
/* we're in HTTP_MSG_DONE now */
|
||||
/* we're in HTTP_MSG_DONE now */
|
||||
}
|
||||
else {
|
||||
int old_state = msg->msg_state;
|
||||
|
||||
if (compressing) {
|
||||
http_compression_buffer_end(s, &res->buf, &tmpbuf, 1);
|
||||
compressing = 0;
|
||||
}
|
||||
|
||||
/* other states, DONE...TUNNEL */
|
||||
/* for keep-alive we don't want to forward closes on DONE */
|
||||
if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_KAL ||
|
||||
@ -5714,7 +5722,7 @@ int http_response_forward_body(struct session *s, struct channel *res, int an_bi
|
||||
}
|
||||
|
||||
missing_data:
|
||||
if (compressing) {
|
||||
if (compressing && consumed_data) {
|
||||
http_compression_buffer_end(s, &res->buf, &tmpbuf, 0);
|
||||
compressing = 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user