From: Ryan Bloom Date: Thu, 17 Aug 2000 00:54:03 +0000 (+0000) Subject: A first pass at the chunking filter. This is incredibly simple. As X-Git-Tag: APACHE_2_0_ALPHA_6~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=032972c119488a2436aa183eef4fe657d03cd3ab;p=thirdparty%2Fapache%2Fhttpd.git A first pass at the chunking filter. This is incredibly simple. As bucket brigades are sent to this filter, it inserts the chunking header at the front of the brigade. When the filter sees an EOS bucket, it adds the 0 chunking trailer. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86090 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 0fd286e0650..013f1bed19d 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -2915,6 +2915,54 @@ static int default_handler(request_rec *r) return OK; } +/* This is an incredibly stupid chunking filter. This will need to be somewhat + * smart about when it actually sends the data, but this implements some sort + * of chunking for right now. + */ +static int chunk_filter(ap_filter_t *f, ap_bucket_brigade *b) +{ + ap_bucket *dptr = b->head; + int len = 0; + int tempint = 0; + char lenstr[6]; + int hit_eos = 0; + + while (dptr) { + if (dptr->type == AP_BUCKET_EOS) { + hit_eos = 1; + } + else { + len += dptr->length; + } + dptr = dptr->next; + } + + apr_snprintf(lenstr, 6, "%x\r\n", len); + dptr = ap_bucket_transient_create(lenstr, 4, &tempint); + b->head->prev = dptr; + dptr->next = b->head; + b->head = dptr; + dptr = ap_bucket_heap_create("\r\n", 2, &tempint); + if (hit_eos) { + b->tail->prev->next = dptr; + dptr->prev = b->tail->prev; + b->tail->prev = dptr; + dptr->next = b->tail; + } + else { + ap_brigade_append_buckets(b, dptr); + } + + if (hit_eos && len != 0) { + apr_snprintf(lenstr, 6, "0\r\n\r\n"); + dptr = ap_bucket_transient_create(lenstr, 5, &tempint); + ap_brigade_append_buckets(b, dptr); + } + + + return ap_pass_brigade(f->next, b); +} + /* Default filter. This filter should almost always be used. It's only job * is to send the headers if they haven't already been sent, and then send * the actual data. To send the data, we create an iovec out of the bucket @@ -3019,9 +3067,9 @@ static void register_hooks(void) /* define the CORE filter, then register a hook to insert it at * request-processing time. */ + ap_hook_insert_filter(core_register_filter, NULL, NULL, AP_HOOK_MIDDLE); ap_register_filter("CORE", core_filter, AP_FTYPE_CONNECTION); - ap_hook_insert_filter(core_register_filter, NULL, NULL, - AP_HOOK_REALLY_LAST); + ap_register_filter("CHUNK", chunk_filter, AP_FTYPE_CONNECTION); } API_VAR_EXPORT module core_module = { diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 7e6e4220513..4cebcce4e89 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -1863,6 +1863,7 @@ API_EXPORT(void) ap_send_http_header(request_rec *r) if (r->chunked) { apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked"); apr_table_unset(r->headers_out, "Content-Length"); + ap_add_filter("CHUNK", NULL, r); } if (r->byterange > 1) @@ -1920,30 +1921,7 @@ API_EXPORT(void) ap_finalize_request_protocol(request_rec *r) { /* tell the filter chain there is no more content coming */ end_output_stream(r); - - if (r->chunked && !r->connection->aborted) { -#ifdef APACHE_XLATE - AP_PUSH_OUTPUTCONVERSION_STATE(r->connection->client, - ap_hdrs_to_ascii); -#endif - /* - * Turn off chunked encoding --- we can only do this once. - */ - r->chunked = 0; - ap_bsetflag(r->connection->client, B_CHUNK, 0); - - (void) checked_bputs("0" CRLF, r); - - /* If we had footer "headers", we'd send them now */ - /* ### these need to be added to allow message digests */ - - (void) checked_bputs(CRLF, r); - -#ifdef APACHE_XLATE - AP_POP_OUTPUTCONVERSION_STATE(r->connection->client); -#endif /*APACHE_XLATE*/ } -} /* Here we deal with getting the request message body from the client. * Whether or not the request contains a body is signaled by the presence