Mercurial > hg > nginx
comparison src/http/modules/ngx_http_gzip_filter_module.c @ 4468:93dd50a9dc70
Gzip filter: handling of empty flush buffers.
Empty flush buffers are legitimate and may happen e.g. due to $r->flush()
calls in embedded perl. If there are no data buffered in zlib, deflate()
will return Z_BUF_ERROR (i.e. no progress possible) without adding anything
to output. Don't treat Z_BUF_ERROR as fatal and correctly send empty flush
buffer if we have no data in output at all.
See this thread for details:
http://mailman.nginx.org/pipermail/nginx/2010-November/023693.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 13 Feb 2012 15:23:43 +0000 |
parents | d620f497c50f |
children | 4a18bf1833a9 63a6b6d70826 |
comparison
equal
deleted
inserted
replaced
4467:85a1570ce960 | 4468:93dd50a9dc70 |
---|---|
757 | 757 |
758 static ngx_int_t | 758 static ngx_int_t |
759 ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) | 759 ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) |
760 { | 760 { |
761 int rc; | 761 int rc; |
762 ngx_buf_t *b; | |
762 ngx_chain_t *cl; | 763 ngx_chain_t *cl; |
763 ngx_http_gzip_conf_t *conf; | 764 ngx_http_gzip_conf_t *conf; |
764 | 765 |
765 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 766 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
766 "deflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d", | 767 "deflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d", |
768 ctx->zstream.avail_in, ctx->zstream.avail_out, | 769 ctx->zstream.avail_in, ctx->zstream.avail_out, |
769 ctx->flush, ctx->redo); | 770 ctx->flush, ctx->redo); |
770 | 771 |
771 rc = deflate(&ctx->zstream, ctx->flush); | 772 rc = deflate(&ctx->zstream, ctx->flush); |
772 | 773 |
773 if (rc != Z_OK && rc != Z_STREAM_END) { | 774 if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) { |
774 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 775 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
775 "deflate() failed: %d, %d", ctx->flush, rc); | 776 "deflate() failed: %d, %d", ctx->flush, rc); |
776 return NGX_ERROR; | 777 return NGX_ERROR; |
777 } | 778 } |
778 | 779 |
817 | 818 |
818 ctx->redo = 0; | 819 ctx->redo = 0; |
819 | 820 |
820 if (ctx->flush == Z_SYNC_FLUSH) { | 821 if (ctx->flush == Z_SYNC_FLUSH) { |
821 | 822 |
822 ctx->zstream.avail_out = 0; | |
823 ctx->out_buf->flush = 1; | |
824 ctx->flush = Z_NO_FLUSH; | 823 ctx->flush = Z_NO_FLUSH; |
825 | 824 |
826 cl = ngx_alloc_chain_link(r->pool); | 825 cl = ngx_alloc_chain_link(r->pool); |
827 if (cl == NULL) { | 826 if (cl == NULL) { |
828 return NGX_ERROR; | 827 return NGX_ERROR; |
829 } | 828 } |
830 | 829 |
831 cl->buf = ctx->out_buf; | 830 b = ctx->out_buf; |
831 | |
832 if (ngx_buf_size(b) == 0) { | |
833 | |
834 b = ngx_calloc_buf(ctx->request->pool); | |
835 if (b == NULL) { | |
836 return NGX_ERROR; | |
837 } | |
838 | |
839 } else { | |
840 ctx->zstream.avail_out = 0; | |
841 } | |
842 | |
843 b->flush = 1; | |
844 | |
845 cl->buf = b; | |
832 cl->next = NULL; | 846 cl->next = NULL; |
833 *ctx->last_out = cl; | 847 *ctx->last_out = cl; |
834 ctx->last_out = &cl->next; | 848 ctx->last_out = &cl->next; |
835 | 849 |
836 return NGX_OK; | 850 return NGX_OK; |