serf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1711392 - in /serf/trunk: buckets/response_buckets.c serf_bucket_types.h
Date Fri, 30 Oct 2015 00:23:19 GMT
Author: rhuijben
Date: Fri Oct 30 00:23:19 2015
New Revision: 1711392

URL: http://svn.apache.org/viewvc?rev=1711392&view=rev
Log:
Make the response bucket follow RFC 7231 a bit more closely by handling
Transfer-Encoding chunked even when content length is passed and when
another transfer-encoding flag is passed. Make the undo of
Content-Encoding optional.

At the same time add Transfer-Encoding gzip support, which unlike
Content-Encoding should be handled by the transport layer.

* buckets/response_buckets.c
  (response_context_t): Add flag.
  (serf_bucket_response_create): Initialize flag.
  (serf_bucket_response_set_decode_content): New function.

* serf_bucket_types.h
  (serf_bucket_response_decode_content): New function.

Modified:
    serf/trunk/buckets/response_buckets.c
    serf/trunk/serf_bucket_types.h

Modified: serf/trunk/buckets/response_buckets.c
URL: http://svn.apache.org/viewvc/serf/trunk/buckets/response_buckets.c?rev=1711392&r1=1711391&r2=1711392&view=diff
==============================================================================
--- serf/trunk/buckets/response_buckets.c (original)
+++ serf/trunk/buckets/response_buckets.c Fri Oct 30 00:23:19 2015
@@ -43,6 +43,7 @@ typedef struct response_context_t {
 
     int chunked;                /* Do we need to read trailers? */
     int head_req;               /* Was this a HEAD request? */
+    int decode_content;         /* Do we want to decode 'Content-Encoding' */
 
     serf_config_t *config;
 
@@ -92,6 +93,7 @@ serf_bucket_t *serf_bucket_response_crea
     ctx->state = STATE_STATUS_LINE;
     ctx->chunked = 0;
     ctx->head_req = 0;
+    ctx->decode_content = TRUE;
     ctx->error_on_eof = 0;
     ctx->config = NULL;
 
@@ -108,6 +110,14 @@ void serf_bucket_response_set_head(
     ctx->head_req = 1;
 }
 
+void serf_bucket_response_set_decode_content(serf_bucket_t *bucket,
+                                             int decode)
+{
+    response_context_t *ctx = bucket->data;
+
+    ctx->decode_content = decode;
+}
+
 serf_bucket_t *serf_bucket_response_get_headers(
     serf_bucket_t *bucket)
 {
@@ -282,7 +292,9 @@ static apr_status_t run_machine(serf_buc
          * Move on to the body.
          */
         if (ctx->linebuf.state == SERF_LINEBUF_READY && !ctx->linebuf.used)
{
-            const void *v;
+            const char *v;
+            int chunked = 0;
+            int gzip = 0;
 
             /* Advance the state. */
             ctx->state = STATE_BODY;
@@ -299,29 +311,62 @@ static apr_status_t run_machine(serf_buc
             ctx->body =
                 serf_bucket_barrier_create(ctx->stream, bkt->allocator);
 
-            /* Are we C-L, chunked, or conn close? */
-            v = serf_bucket_headers_get(ctx->headers, "Content-Length");
+            /* Are we chunked, C-L, or conn close? */
+            v = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding");
+
+            /* Need a copy cuz we're going to write NUL characters into the
+               string.  */
             if (v) {
-                apr_uint64_t length;
-                length = apr_strtoi64(v, NULL, 10);
-                if (errno == ERANGE) {
-                    return APR_FROM_OS_ERROR(ERANGE);
+                char *attrs = serf_bstrdup(bkt->allocator, v);
+                char *at = attrs;
+                char *next = NULL;
+
+                while ((v = apr_strtok(at, ", ", &next))) {
+                  at = NULL;
+
+                  if (!strcasecmp(v, "chunked"))
+                      chunked = 1;
+                  else if (!strcasecmp(v, "gzip"))
+                      gzip = 1;
+                  /* ### Others? */
                 }
-                ctx->body = serf_bucket_response_body_create(
-                              ctx->body, length, bkt->allocator);
+                serf_bucket_mem_free(bkt->allocator, attrs);
             }
-            else {
-                v = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding");
 
-                /* Need to handle multiple transfer-encoding. */
-                if (v && strcasecmp("chunked", v) == 0) {
-                    ctx->chunked = 1;
-                    ctx->body = serf_bucket_dechunk_create(ctx->body,
-                                                           bkt->allocator);
+            if (chunked) {
+                ctx->chunked = 1;
+                ctx->body = serf_bucket_dechunk_create(ctx->body,
+                                                       bkt->allocator);
+                serf_bucket_set_config(ctx->body, ctx->config);
+            }
+            else {
+                /* RFC 7231 specifies that we should determine the message
+                   length via Transfer-Encoding chunked, when both chunked
+                   and Content-Length are passed */
+
+                v = serf_bucket_headers_get(ctx->headers, "Content-Length");
+                if (v) {
+                    apr_uint64_t length;
+                    length = apr_strtoi64(v, NULL, 10);
+                    if (errno == ERANGE) {
+                        return APR_FROM_OS_ERROR(ERANGE);
+                    }
+                    ctx->body = serf_bucket_response_body_create(
+                                  ctx->body, length, bkt->allocator);
                 }
             }
+
+            /* Transfer encodings are handled by the transport, while content
+               encoding is part of the data itself. */
+            if (gzip) {
+                ctx->body =
+                    serf_bucket_deflate_create(ctx->body, bkt->allocator,
+                                               SERF_DEFLATE_GZIP);
+                serf_bucket_set_config(ctx->body, ctx->config);
+            }
+
             v = serf_bucket_headers_get(ctx->headers, "Content-Encoding");
-            if (v) {
+            if (v && ctx->decode_content) {
                 /* Need to handle multiple content-encoding. */
                 if (v && strcasecmp("gzip", v) == 0) {
                     ctx->body =

Modified: serf/trunk/serf_bucket_types.h
URL: http://svn.apache.org/viewvc/serf/trunk/serf_bucket_types.h?rev=1711392&r1=1711391&r2=1711392&view=diff
==============================================================================
--- serf/trunk/serf_bucket_types.h (original)
+++ serf/trunk/serf_bucket_types.h Fri Oct 30 00:23:19 2015
@@ -138,6 +138,16 @@ serf_bucket_t *serf_bucket_response_get_
 void serf_bucket_response_set_head(
     serf_bucket_t *bucket);
 
+/**
+ * Ask the response @a bucket, to decode content based on the value of the
+ * 'Content- Encoding' header, or not. The default setting of a response
+ * bucket is to decode when the header is found.
+ */
+void serf_bucket_response_decode_content(
+    serf_bucket_t *bucket,
+    int decode);
+
+
 /* ==================================================================== */
 
 extern const serf_bucket_type_t serf_bucket_type_response_body;



Mime
View raw message