3131#include " pagespeed/kernel/base/statistics.h"
3232#include " pagespeed/kernel/base/string.h"
3333#include " pagespeed/kernel/base/string_util.h"
34- #include " pagespeed/kernel/base/string_writer.h"
3534#include " pagespeed/kernel/base/timer.h"
3635#include " pagespeed/kernel/cache/cache_interface.h"
36+ #include " pagespeed/kernel/http/content_type.h"
3737#include " pagespeed/kernel/http/google_url.h"
3838#include " pagespeed/kernel/http/http_names.h"
3939#include " pagespeed/kernel/http/response_headers.h"
@@ -229,7 +229,17 @@ class HTTPCacheCallback : public CacheInterface::Callback {
229229 headers->IsProxyCacheable (callback_->req_properties (),
230230 callback_->RespectVaryOnResources (),
231231 ResponseHeaders::kHasValidator )) {
232- callback_->fallback_http_value ()->Link (callback_->http_value ());
232+ ResponseHeaders fallback_headers;
233+ if (callback_->request_context ()->accepts_gzip () ||
234+ !callback_->http_value ()->ExtractHeaders (&fallback_headers,
235+ handler_) ||
236+ !InflatingFetch::UnGzipValueIfCompressed (
237+ *callback_->http_value (), &fallback_headers,
238+ callback_->fallback_http_value (), handler_)) {
239+ // If we don't need to unzip, or can't unzip, then just
240+ // link the value and fallback together.
241+ callback_->fallback_http_value ()->Link (callback_->http_value ());
242+ }
233243 }
234244 }
235245 }
@@ -249,10 +259,14 @@ class HTTPCacheCallback : public CacheInterface::Callback {
249259 if (result_.status != HTTPCache::kFound ) {
250260 headers->Clear ();
251261 callback_->http_value ()->Clear ();
252- }
253- if (!callback_->request_context ()->accepts_gzip ()) {
254- HTTPValue* http_value = callback_->http_value ();
255- InflatingFetch::UnGzipValueIfCompressed (http_value, headers, handler_);
262+ } else if (!callback_->request_context ()->accepts_gzip () &&
263+ headers->IsGzipped ()) {
264+ HTTPValue new_value;
265+ GoogleString inflated;
266+ if (InflatingFetch::UnGzipValueIfCompressed (
267+ *callback_->http_value (), headers, &new_value, handler_)) {
268+ callback_->http_value ()->Link (&new_value);
269+ }
256270 }
257271 start_ms_ = now_ms;
258272 start_us_ = now_us;
@@ -380,7 +394,8 @@ HTTPValue* HTTPCache::ApplyHeaderChangesForPut(
380394 return value;
381395}
382396
383- void HTTPCache::PutInternal (const GoogleString& key,
397+ void HTTPCache::PutInternal (bool preserve_response_headers,
398+ const GoogleString& key,
384399 const GoogleString& fragment, int64 start_us,
385400 HTTPValue* value, ResponseHeaders* response_headers,
386401 MessageHandler* handler) {
@@ -394,13 +409,23 @@ void HTTPCache::PutInternal(const GoogleString& key,
394409 if (!value->Empty () && compression_level_ != 0 ) {
395410 const ContentType* type = response_headers->DetermineContentType ();
396411 if ((type != NULL ) && type->IsCompressible () &&
397- !response_headers->IsGzipped () &&
398- InflatingFetch::GzipValue (compression_level_, value, &compressed_value,
399- response_headers, handler)) {
400- // The resource is text (js, css, html, svg, etc.), and not previously
401- // compressed, so we'll compress it and stick the new compressed version
402- // in the cache.
403- value = &compressed_value;
412+ !response_headers->IsGzipped ()) {
413+ ResponseHeaders* headers_to_gzip = response_headers;
414+ ResponseHeaders headers_copy;
415+ if (preserve_response_headers) {
416+ headers_copy.CopyFrom (*response_headers);
417+ headers_to_gzip = &headers_copy;
418+ }
419+ headers_to_gzip->ComputeCaching ();
420+
421+ if (InflatingFetch::GzipValue (compression_level_, *value,
422+ &compressed_value, headers_to_gzip,
423+ handler)) {
424+ // The resource is text (js, css, html, svg, etc.), and not previously
425+ // compressed, so we'll compress it and stick the new compressed version
426+ // in the cache.
427+ value = &compressed_value;
428+ }
404429 }
405430 }
406431 // TODO(jcrowell): prevent the unzip-rezip flow when sending compressed data
@@ -442,7 +467,8 @@ void HTTPCache::Put(const GoogleString& key, const GoogleString& fragment,
442467 start_us, NULL , &headers, value, handler);
443468 // Put into underlying cache.
444469 if (new_value != NULL ) {
445- PutInternal (key, fragment, start_us, new_value, &headers, handler);
470+ PutInternal (false /* preserve_response_headers */ ,
471+ key, fragment, start_us, new_value, &headers, handler);
446472 if (cache_inserts_ != NULL ) {
447473 cache_inserts_->Add (1 );
448474 }
@@ -478,7 +504,8 @@ void HTTPCache::Put(const GoogleString& key, const GoogleString& fragment,
478504 ApplyHeaderChangesForPut (start_us, &content, headers, NULL , handler));
479505 // Put into underlying cache.
480506 if (value.get () != NULL ) {
481- PutInternal (key, fragment, start_us, value.get (), headers, handler);
507+ PutInternal (true /* preserve_response_headers */ ,
508+ key, fragment, start_us, value.get (), headers, handler);
482509 if (cache_inserts_ != NULL ) {
483510 cache_inserts_->Add (1 );
484511 }
0 commit comments