You are viewing a plain text version of this content. The canonical link for it is here.
Posted to apache-bugdb@apache.org by Ronald Tschalaer <Ro...@psi.ch> on 1998/02/05 04:01:57 UTC

mod_negotiation/1772: Can't handle both "Accept-Encoding: gzip" and "Accept-Encoding: x-gzip"

>Number:         1772
>Category:       mod_negotiation
>Synopsis:       Can't handle both "Accept-Encoding: gzip" and "Accept-Encoding: x-gzip"
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache
>State:          open
>Class:          sw-bug
>Submitter-Id:   apache
>Arrival-Date:   Wed Feb  4 19:10:01 PST 1998
>Last-Modified:
>Originator:     Ronald.Tschalaer@psi.ch
>Organization:
apache
>Release:        1.3b3 (and 1.2.x)
>Environment:
All environments
>Description:
According the HTTP/1.1 specs gzip and x-gzip (and compress and x-compress)
should be considered equivalent. This is especially important so that new
clients can start using the gzip (and compress) tokens, but the server can
still handle older clients correctly. However, one cannot use the following
in the config:

AddEncoding gzip gz
AddEncoding x-gzip gz

because the internal encoding table is keyed off the file extension ("gz" in
this case). Therefore, I have created a couple patches, one for mod_mime and
one for mod_negotiation, which attempt to fix this.

The idea is that any "x-" prefix in either an AddEncoding directive or in an
Accept-Encoding header is stripped before the comparison is made. In addition,
to deal with older clients that expect a "Content-Encoding: x-gzip" (and which
would probably barf on a "Content-Encoding: gzip") the Content-Encoding header
returned will contain the x- token if the x- token was used in the
Accept-Encoding.

Note that this patch will cause *all* x-YYY tokens to be treated as YYY.
However, I dont' think this is a problem. In fact, one could probably
consider it a feature, since now no changes to any server code are required
when an x-YYY token is officially adopted as YYY.
>How-To-Repeat:
Using the standard configuration files (which contains "AddEncoding x-gzip gz")
send a request for a resource which has both a gzip'd and a plain version
available, using the "Accept-Encoding: gzip" header instead of the
"Accept-Encoding: x-gzip" header. You will then get the plain version instead
of the gzip'd one.
>Fix:
Here are my suggested patches to mod_negotiation and mod_mime. Note that
since I'm not intimately familiar with mod_negotiation, I'm not sure if
the complete if() in the second patch block (lines 2188-2204) is really
necessary. I.e., is the value of "best->content_encoding" always the same
as "sub_req->content_encoding"? If so, the code can be simplified.

-------------------------------------------------------------------------
mithrandir[standard] diff -c mod_negotiation.c{.orig,}
*** mod_negotiation.c.orig      Wed Oct 22 22:30:26 1997
--- mod_negotiation.c   Thu Feb  5 03:22:26 1998
***************
*** 1482,1490 ****
       */
      for (i = 0; i < neg->accept_encodings->nelts; ++i) {
          char *name = accept_recs[i].type_name;
  
!         if (!strcmp(name, enc)) {
              variant->encoding_quality = 1;
              return;
          }
      }
--- 1482,1495 ----
       */
      for (i = 0; i < neg->accept_encodings->nelts; ++i) {
          char *name = accept_recs[i].type_name;
+         int off = 0;
  
!         if (!strncmp(name, "x-", 2))
!             off = 2;
! 
!         if (!strcmp(name+off, enc)) {
              variant->encoding_quality = 1;
+             variant->content_encoding = name;
              return;
          }
      }
***************
*** 2183,2189 ****
      r->filename = sub_req->filename;
      r->handler = sub_req->handler;
      r->content_type = sub_req->content_type;
!     r->content_encoding = sub_req->content_encoding;
      r->content_languages = sub_req->content_languages;
      r->content_language = sub_req->content_language;
      r->finfo = sub_req->finfo;
--- 2188,2204 ----
      r->filename = sub_req->filename;
      r->handler = sub_req->handler;
      r->content_type = sub_req->content_type;
!     if (strncmp(best->content_encoding, "x-", 2) == 0  &&
!         strcmp(best->content_encoding+2, sub_req->content_encoding) == 0) {
!         /* return "Content-Encoding: x-gzip" if "Accept-Encoding: x-gzip"
!          * Is the last strcmp() always true? If so, we could leave out
!          * the complete if() and just use the line below
!          */
!         r->content_encoding = best->content_encoding;
!     }
!     else {
!         r->content_encoding = sub_req->content_encoding;
!     }
      r->content_languages = sub_req->content_languages;
      r->content_language = sub_req->content_language;
      r->finfo = sub_req->finfo;
mithrandir[standard] diff -c mod_mime.c{.orig,}
*** mod_mime.c.orig     Sun Oct 26 21:20:05 1997
--- mod_mime.c  Thu Feb  5 03:23:00 1998
***************
*** 127,132 ****
--- 127,134 ----
  {
      if (*ext == '.')
          ++ext;
+     if (!strncasecmp(enc, "x-", 2))
+         enc += 2;
      table_set(m->encoding_types, ext, enc);
      return NULL;
  }
------------------------------------------------------------------------
>Audit-Trail:
>Unformatted:
[In order for any reply to be added to the PR database, ]
[you need to include <ap...@Apache.Org> in the Cc line ]
[and leave the subject line UNCHANGED.  This is not done]
[automatically because of the potential for mail loops. ]