Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Attempt to make progress on PR39727/PR45023 blocking migration
to 2.4.  Provide DeflateAlterETag directive to choose between 
2.2 behavior, 2.4 behavior, or dropping ETag from the compressed
representation.

Preserves 2.4 default which breas 304 responses for compressed content.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1586542 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
covener committed Apr 11, 2014
1 parent bff3909 commit 0eb1b00
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGES
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.0

*) mod_deflate: Add DeflateAlterETag to control how the ETag
is modified. The 'NoChange' parameter mimics 2.2.x behavior.
PR 45023, PR 39727. [Eric Covener]

*) mod_ssl: fix merging of global and vhost-level settings with the
SSLCertificateFile, SSLCertificateKeyFile, and SSLOpenSSLConfCmd
directives. PR 56353. [Kaspar Brand]
Expand Down
30 changes: 30 additions & 0 deletions docs/manual/mod/mod_deflate.xml
Expand Up @@ -298,6 +298,36 @@ CustomLog logs/deflate_log deflate
</usage>
</directivesynopsis>

<directivesynopsis>
<name>DeflateAlterETag</name>
<description>How the outgoing ETag header should be modified during compression</description>
<syntax>DeflateAlterETag AddSuffix|NoChange|Remove</syntax>
<default>DeflateAlterETag AddSuffix</default>
<contextlist><context>server config</context><context>virtual host</context>
</contextlist>

<usage>
<p>The <directive>DeflateAlterETag</directive> directive specifies
how the ETag hader should be altered when a response is compressed.</p>
<dl>
<dt>AddSuffix</dt>
<dd><p>Append the compression method onto the end of the ETag, causing
compressed and uncompressed representatins to have unique ETags.
This has been the default since 2.4.0, but prevents serving
"HTTP Not Modified" (304) responses to conditional requests for
compressed content.</p></dd>
<dt>NoChange</dt>
<dd><p>Don't change the ETag on a compressed response. This was the default
prior to 2.4.0, but does not satisfy the HTTP/1.1 property that all
representations of the same resource have unique ETags </p></dd>
<dt>Remove</dt>
<dd><p>Remove the ETag header from compressed responses. This prevents
some conditional requests from being possible, but avoids the
shortcomings of the preceding options. </p></dd>
</dl>
</usage>
</directivesynopsis>


</modulesynopsis>

46 changes: 43 additions & 3 deletions modules/filters/mod_deflate.c
Expand Up @@ -54,6 +54,10 @@
static const char deflateFilterName[] = "DEFLATE";
module AP_MODULE_DECLARE_DATA deflate_module;

#define AP_DEFLATE_ETAG_ADDSUFFIX 0
#define AP_DEFLATE_ETAG_NOCHANGE 1
#define AP_DEFLATE_ETAG_REMOVE 2

typedef struct deflate_filter_config_t
{
int windowSize;
Expand All @@ -63,6 +67,7 @@ typedef struct deflate_filter_config_t
char *note_ratio_name;
char *note_input_name;
char *note_output_name;
int etag_opt;
} deflate_filter_config;

/* RFC 1952 Section 2.3 defines the gzip header:
Expand Down Expand Up @@ -280,6 +285,29 @@ static const char *deflate_set_memlevel(cmd_parms *cmd, void *dummy,
return NULL;
}

static const char *deflate_set_etag(cmd_parms *cmd, void *dummy,
const char *arg)
{
deflate_filter_config *c = ap_get_module_config(cmd->server->module_config,
&deflate_module);

if (!strcasecmp(arg, "NoChange")) {
c->etag_opt = AP_DEFLATE_ETAG_NOCHANGE;
}
else if (!strcasecmp(arg, "AddSuffix")) {
c->etag_opt = AP_DEFLATE_ETAG_ADDSUFFIX;
}
else if (!strcasecmp(arg, "Remove")) {
c->etag_opt = AP_DEFLATE_ETAG_REMOVE;
}
else {
return "DeflateAlterETAG accepts only 'NoChange', 'AddSuffix', and 'Remove'";
}

return NULL;
}


static const char *deflate_set_compressionlevel(cmd_parms *cmd, void *dummy,
const char *arg)
{
Expand Down Expand Up @@ -398,11 +426,16 @@ static apr_status_t deflate_ctx_cleanup(void *data)
* value inside the double-quotes if an ETag has already been set
* and its value already contains double-quotes. PR 39727
*/
static void deflate_check_etag(request_rec *r, const char *transform)
static void deflate_check_etag(request_rec *r, const char *transform, int etag_opt)
{
const char *etag = apr_table_get(r->headers_out, "ETag");
apr_size_t etaglen;

if (etag_opt == AP_DEFLATE_ETAG_REMOVE) {
apr_table_unset(r->headers_out, "ETag");
return;
}

if ((etag && ((etaglen = strlen(etag)) > 2))) {
if (etag[etaglen - 1] == '"') {
apr_size_t transformlen = strlen(transform);
Expand Down Expand Up @@ -708,7 +741,9 @@ static apr_status_t deflate_out_filter(ap_filter_t *f,
}
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Content-MD5");
deflate_check_etag(r, "gzip");
if (c->etag_opt != AP_DEFLATE_ETAG_NOCHANGE) {
deflate_check_etag(r, "gzip", c->etag_opt);
}

/* For a 304 response, only change the headers */
if (r->status == HTTP_NOT_MODIFIED) {
Expand Down Expand Up @@ -1401,7 +1436,9 @@ static apr_status_t inflate_out_filter(ap_filter_t *f,
*/
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Content-MD5");
deflate_check_etag(r, "gunzip");
if (c->etag_opt != AP_DEFLATE_ETAG_NOCHANGE) {
deflate_check_etag(r, "gunzip", c->etag_opt);
}

/* For a 304 response, only change the headers */
if (r->status == HTTP_NOT_MODIFIED) {
Expand Down Expand Up @@ -1741,6 +1778,9 @@ static const command_rec deflate_filter_cmds[] = {
"Set the Deflate Memory Level (1-9)"),
AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
"Set the Deflate Compression Level (1-9)"),
AP_INIT_TAKE1("DeflateAlterEtag", deflate_set_etag, NULL, RSRC_CONF,
"Set how mod_deflate should modify ETAG response headers: 'AddSuffix' (default), 'NoChange' (2.2.x behavior), 'Remove'"),

{NULL}
};

Expand Down

0 comments on commit 0eb1b00

Please sign in to comment.