Mercurial > hg > nginx
view src/http/modules/ngx_http_chunked_filter.c @ 461:a88a3e4e158f release-0.1.5
nginx-0.1.5-RELEASE import
*) Bugfix: on Solaris and Linux there may be too many "recvmsg()
returned not enough data" alerts.
*) Bugfix: there were the "writev() failed (22: Invalid argument)"
errors on Solaris in proxy mode without sendfile. On other platforms
that do not support sendfile at all the process got caught in an
endless loop.
*) Bugfix: segmentation fault on Solaris in proxy mode and using
sendfile.
*) Bugfix: segmentation fault on Solaris.
*) Bugfix: on-line upgrade did not work on Linux.
*) Bugfix: the ngx_http_autoindex_module module did not escape the
spaces, the quotes, and the percent signs in the directory listing.
*) Change: the decrease of the copy operations.
*) Feature: the userid_p3p directive.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 11 Nov 2004 14:07:14 +0000 |
parents | 295d97d70c69 |
children | 8e8f3af115b5 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle); static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { NULL, /* pre conf */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ NULL, /* create location configuration */ NULL, /* merge location configuration */ }; ngx_module_t ngx_http_chunked_filter_module = { NGX_MODULE, &ngx_http_chunked_filter_module_ctx, /* module context */ NULL, /* module directives */ NGX_HTTP_MODULE, /* module type */ ngx_http_chunked_filter_init, /* init module */ NULL /* init process */ }; static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t ngx_http_chunked_header_filter(ngx_http_request_t *r) { if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { return ngx_http_next_header_filter(r); } if (r->headers_out.content_length_n == -1) { if (r->http_version < NGX_HTTP_VERSION_11) { r->keepalive = 0; } else { r->chunked = 1; } } return ngx_http_next_header_filter(r); } static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { u_char *chunk; size_t size; ngx_buf_t *b; ngx_chain_t out, tail, *cl, *tl, **ll; if (in == NULL || !r->chunked) { return ngx_http_next_body_filter(r, in); } out.buf = NULL; ll = &out.next; size = 0; cl = in; for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http chunk: %d", ngx_buf_size(cl->buf)); size += ngx_buf_size(cl->buf); if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) { if (!(tl = ngx_alloc_chain_link(r->pool))) { return NGX_ERROR; } tl->buf = cl->buf; *ll = tl; ll = &tl->next; } if (cl->next == NULL) { break; } cl = cl->next; } if (size) { if (!(b = ngx_calloc_buf(r->pool))) { return NGX_ERROR; } if (!(chunk = ngx_palloc(r->pool, sizeof("00000000" CRLF) - 1))) { return NGX_ERROR; } b->temporary = 1; b->pos = chunk; b->last = ngx_sprintf(chunk, "%xz" CRLF, size); out.buf = b; } if (cl->buf->last_buf) { if (!(b = ngx_calloc_buf(r->pool))) { return NGX_ERROR; } b->memory = 1; b->last_buf = 1; b->pos = (u_char *) CRLF "0" CRLF CRLF; b->last = b->pos + 7; cl->buf->last_buf = 0; if (size == 0) { b->pos += 2; out.buf = b; out.next = NULL; return ngx_http_next_body_filter(r, &out); } } else { if (size == 0) { *ll = NULL; return ngx_http_next_body_filter(r, out.next); } if (!(b = ngx_calloc_buf(r->pool))) { return NGX_ERROR; } b->memory = 1; b->pos = (u_char *) CRLF; b->last = b->pos + 2; } tail.buf = b; tail.next = NULL; *ll = &tail; return ngx_http_next_body_filter(r, &out); } static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle) { ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_chunked_header_filter; ngx_http_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_chunked_body_filter; return NGX_OK; }