]> granicus.if.org Git - apache/commitdiff
Use the content-length filter to compute the content-length for byterange
authorRyan Bloom <rbb@apache.org>
Thu, 9 Nov 2000 03:33:24 +0000 (03:33 +0000)
committerRyan Bloom <rbb@apache.org>
Thu, 9 Nov 2000 03:33:24 +0000 (03:33 +0000)
requests.  This allows the byterange filter to work with the PDF plug-in.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86880 13f79535-47bb-0310-9956-ffa450edef68

modules/http/http_core.c
modules/http/http_protocol.c

index 5d7ff22a76e83c1f95e7885828021c7cd3203add..0fb8fec89504f1463581faf2b1ae280ade421ac1 100644 (file)
@@ -3549,13 +3549,13 @@ static void register_hooks(void)
                               AP_FTYPE_HTTP_HEADER);
     ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter, 
                               AP_FTYPE_HTTP_HEADER);
+    ap_register_output_filter("BYTERANGE", ap_byterange_filter, 
+                              AP_FTYPE_HTTP_HEADER);
     ap_register_output_filter("CORE", core_output_filter, AP_FTYPE_NETWORK);
     ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter, 
                               AP_FTYPE_CONTENT);
     ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
     ap_register_output_filter("COALESCE", coalesce_filter, AP_FTYPE_CONNECTION);
-    ap_register_output_filter("BYTERANGE", ap_byterange_filter, 
-                              AP_FTYPE_TRANSCODE);
 }
 
 AP_DECLARE_DATA module core_module = {
index d002027ca3154fe04d53560a87ead8dce9089964..82a59d86249023e8b4f08020177eced5e945420c 100644 (file)
@@ -179,9 +179,10 @@ static int parse_byterange(char *range, apr_off_t clength,
     return (*start > 0 || *end < clength - 1);
 }
 
+static int ap_set_byterange(request_rec *r);
+
 typedef struct byterange_ctx {
     ap_bucket_brigade *bb;
-    const char *bound_head;
     int num_ranges;
 } byterange_ctx;
 
@@ -199,6 +200,20 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
     apr_off_t range_start;
     apr_off_t range_end;
     char *current;
+    const char *bound_head;
+    const char *ct = make_content_type(r, r->content_type);
+
+    if (!ctx) {
+        int num_ranges = ap_set_byterange(r);
+        if (num_ranges == 0) {
+            ap_remove_output_filter(f);
+            return ap_pass_brigade(f->next, bb);
+        }
+        ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
+        ctx->num_ranges = ap_set_byterange(r);
+        
+    }
 
     /* We can't actually deal with byte-ranges until we have the whole brigade
      * because the byte-ranges can be in any order, and according to the RFC,
@@ -209,6 +224,12 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
         return APR_SUCCESS;
     }
 
+    /* compute this once (it is an invariant) and store it away */
+    bound_head = apr_pstrcat(r->pool, CRLF "--", r->boundary,
+                                  CRLF "Content-type: ", ct,
+                                  CRLF "Content-range: bytes ", 
+                                  NULL);
+
     /* concat the passed brigade with our saved brigade */
     AP_BRIGADE_CONCAT(ctx->bb, bb);
     bb = ctx->bb;
@@ -247,7 +268,8 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
         */
 
         ap_bucket_read(e, &str, &n, AP_NONBLOCK_READ);
-        /* ### using e->length doesn't account for pipes */
+        /* using e->length doesn't account for pipes once we change the read
+         * to a split.*/
         while (range_start > (curr_offset + e->length)) {
             curr_offset += e->length;
             e = AP_BUCKET_NEXT(e);
@@ -256,14 +278,14 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
                 break;
             }
 
-            /* ### eventually we can avoid this */
+            /* eventually we can avoid this */
             ap_bucket_read(e, &str, &n, AP_NONBLOCK_READ);
         }
         if (range_start != curr_offset) {
             /* If we get here, then we know that the beginning of this 
              * byte-range occurs someplace in the middle of the current bucket
              */
-            /* ### when we split above, we should read here */
+            /* when we split above, we should read here */
             segment_length = MIN_LENGTH(curr_length + 1, e->length);
             memcpy(loc, str + (range_start - curr_offset), segment_length);
             loc += segment_length;
@@ -289,8 +311,8 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
         if (ctx->num_ranges > 1) {
             const char *ts;
 
-            e = ap_bucket_create_pool(ctx->bound_head,
-                                      strlen(ctx->bound_head), r->pool);
+            e = ap_bucket_create_pool(bound_head,
+                                      strlen(bound_head), r->pool);
             AP_BRIGADE_INSERT_TAIL(bsend, e);
 
             ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
@@ -1371,6 +1393,7 @@ request_rec *ap_read_request(conn_rec *conn)
                      ? r->server->keep_alive_timeout * APR_USEC_PER_SEC
                      : r->server->timeout * APR_USEC_PER_SEC);
                      
+    ap_add_output_filter("BYTERANGE", NULL, r, r->connection);
     ap_add_output_filter("CONTENT_LENGTH", NULL, r, r->connection);
     ap_add_output_filter("HTTP_HEADER", NULL, r, r->connection);
 
@@ -2331,7 +2354,7 @@ static int ap_set_byterange(request_rec *r)
             return 0;
     }
 
-    /* ### would be nice to pick this up from f->ctx */
+    /* would be nice to pick this up from f->ctx */
     ct = make_content_type(r, r->content_type);
 
     if (!ap_strchr_c(range, ',')) {
@@ -2345,18 +2368,11 @@ static int ap_set_byterange(request_rec *r)
         apr_table_setn(r->headers_out, "Content-Range",
                        apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
                                     range_start, range_end, r->clength));
-        apr_table_setn(r->headers_out, "Content-Length",
-                       apr_psprintf(r->pool, "%" APR_OFF_T_FMT,
-                                    range_end - range_start + 1));
        apr_table_setn(r->headers_out, "Content-Type", ct);
 
         num_ranges = 1;
     }
     else {
-        const char *work_range = range;
-        char *current;
-        apr_off_t tlength = 0;
-
         /* a multiple range */
 
         num_ranges = 2;
@@ -2365,30 +2381,6 @@ static int ap_set_byterange(request_rec *r)
         r->boundary = apr_psprintf(r->pool, "%qx%lx",
                                    r->request_time, (long) getpid());
 
-        /* compute the length for the actual data plus the boundary headers */
-        while ((current = ap_getword(r->pool, &work_range, ','))
-               && parse_byterange(current, r->clength,
-                                  &range_start, &range_end)) {
-            char rng[MAX_STRING_LEN];
-
-            apr_snprintf(rng, sizeof(rng), BYTERANGE_FMT,
-                         range_start, range_end, r->clength);
-            /* CRLF "--" boundary
-               CRLF "Content-type: " ct
-               CRLF "Content-range: bytes " rng
-               CRLF CRLF
-               content
-            */
-            tlength += (4 + strlen(r->boundary) + 16 + strlen(ct) +
-                        23 + strlen(rng) + 4 +
-                        range_end - range_start + 1);
-        }
-
-        /* add final boundary length: CRLF "--" boundary "--" CRLF */
-        tlength += 4 + strlen(r->boundary) + 4;
-
-        apr_table_setn(r->headers_out, "Content-Length",
-                       apr_psprintf(r->pool, "%" APR_OFF_T_FMT, tlength));
         apr_table_setn(r->headers_out, "Content-Type",
                       apr_pstrcat(r->pool,
                                    "multipart", use_range_x(r) ? "/x-" : "/",
@@ -2402,25 +2394,6 @@ static int ap_set_byterange(request_rec *r)
     return num_ranges;
 }
 
-static void add_byterange_filter(request_rec *r, int num_ranges)
-{
-    byterange_ctx *ctx = apr_pcalloc(r->pool, sizeof(*ctx));
-    const char *ct = make_content_type(r, r->content_type);
-
-    /* we will always need this */
-    ctx->bb = ap_brigade_create(r->pool);
-
-    /* compute this once (it is an invariant) and store it away */
-    ctx->bound_head = apr_pstrcat(r->pool, CRLF "--", r->boundary,
-                                  CRLF "Content-type: ", ct,
-                                  CRLF "Content-range: bytes ", 
-                                  NULL);
-
-    ctx->num_ranges = num_ranges;
-
-    ap_add_output_filter("BYTERANGE", ctx, r, r->connection);
-}
-
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bucket_brigade *b)
 {
     int i;
@@ -2431,7 +2404,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bu
     ap_bucket_brigade *b2;
     apr_size_t len = 0;
     header_struct h;
-    int num_ranges;
 
     AP_DEBUG_ASSERT(!r->main);
 
@@ -2475,8 +2447,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bu
 /*      ap_add_output_filter("COALESCE", NULL, r, r->connection); */
     }
 
-    num_ranges = ap_set_byterange(r);
-
     if (r->content_encoding) {
         apr_table_setn(r->headers_out, "Content-Encoding",
                       r->content_encoding);
@@ -2536,11 +2506,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ap_bu
          */
         ap_add_output_filter("CHUNK", NULL, r, r->connection);
     }
-    if (num_ranges) {
-        /* wait until the headers have been sent before adding the byterange
-           filter */
-        add_byterange_filter(r, num_ranges);
-    }
 
     /* Don't remove this filter until after we have added the CHUNK filter.
      * Otherwise, f->next won't be the CHUNK filter and thus the first