Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.

Commit 7a3fab0

Browse files
jeffkaufmancrowell
authored andcommitted
If we're receiving a response slowly and the user aborts, we need to note this and not record the truncated resource to cache.
Fixes #1081 Nginx side of the change: apache/incubator-pagespeed-ngx#966
1 parent fcfc4f5 commit 7a3fab0

File tree

4 files changed

+49
-9
lines changed

4 files changed

+49
-9
lines changed

net/instaweb/apache/mod_instaweb.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,9 @@ apr_status_t instaweb_in_place_check_headers_filter(ap_filter_t* filter,
818818
// We now have the final headers. If they don't let us cache then we'll
819819
// abort even though we've already buffered up the whole resource.
820820
InstawebHandler::AboutToBeDoneWithRecorder(request, recorder);
821-
recorder->DoneAndSetHeaders(&response_headers); // Deletes recorder.
821+
// Deletes recorder
822+
recorder->DoneAndSetHeaders(&response_headers,
823+
!request->connection->aborted);
822824
}
823825
}
824826

net/instaweb/system/in_place_resource_recorder.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,13 @@ void InPlaceResourceRecorder::DroppedDueToSize() {
208208
}
209209

210210
void InPlaceResourceRecorder::DoneAndSetHeaders(
211-
ResponseHeaders* response_headers) {
211+
ResponseHeaders* response_headers, bool entire_response_received) {
212+
if (!entire_response_received) {
213+
// To record successfully, we must have a complete response. Otherwise you
214+
// get https://github.com/pagespeed/mod_pagespeed/issues/1081.
215+
Fail();
216+
}
217+
212218
if (!failure_ && !full_response_headers_considered_) {
213219
ConsiderResponseHeaders(kFullHeaders, response_headers);
214220
}

net/instaweb/system/in_place_resource_recorder_test.cc

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ class InPlaceResourceRecorderTest : public RewriteTestBase {
9797
StringPiece gzipped(reinterpret_cast<const char*>(&kGzippedData[0]),
9898
STATIC_STRLEN(kGzippedData));
9999
recorder->Write(gzipped, message_handler());
100-
recorder.release()->DoneAndSetHeaders(&final_headers);
100+
recorder.release()->DoneAndSetHeaders(
101+
&final_headers, true /* complete response */);
101102

102103
HTTPValue value_out;
103104
ResponseHeaders headers_out;
@@ -160,7 +161,8 @@ TEST_F(InPlaceResourceRecorderTest, BasicOperation) {
160161
InPlaceResourceRecorder::kPreliminaryHeaders, &prelim_headers);
161162
recorder->Write(kHello, message_handler());
162163
recorder->Write(kBye, message_handler());
163-
recorder.release()->DoneAndSetHeaders(&ok_headers);
164+
recorder.release()->DoneAndSetHeaders(
165+
&ok_headers, true /* complete response */);
164166

165167
HTTPValue value_out;
166168
ResponseHeaders headers_out;
@@ -171,6 +173,26 @@ TEST_F(InPlaceResourceRecorderTest, BasicOperation) {
171173
EXPECT_EQ(StrCat(kHello, kBye), contents);
172174
}
173175

176+
TEST_F(InPlaceResourceRecorderTest, IncompleteResponse) {
177+
ResponseHeaders prelim_headers;
178+
prelim_headers.set_status_code(HttpStatus::kOK);
179+
180+
ResponseHeaders ok_headers;
181+
SetDefaultLongCacheHeaders(&kContentTypeCss, &ok_headers);
182+
183+
scoped_ptr<InPlaceResourceRecorder> recorder(MakeRecorder(kTestUrl));
184+
recorder->ConsiderResponseHeaders(
185+
InPlaceResourceRecorder::kPreliminaryHeaders, &prelim_headers);
186+
recorder->Write(kHello, message_handler());
187+
recorder.release()->DoneAndSetHeaders(
188+
&ok_headers, false /* incomplete response */);
189+
190+
HTTPValue value_out;
191+
ResponseHeaders headers_out;
192+
EXPECT_EQ(HTTPCache::kNotFound,
193+
HttpBlockingFind(kTestUrl, http_cache(), &value_out, &headers_out));
194+
}
195+
174196
TEST_F(InPlaceResourceRecorderTest, CheckCacheableContentTypes) {
175197
CheckCacheableContentType(&kContentTypeJpeg);
176198
CheckCacheableContentType(&kContentTypeCss);
@@ -192,7 +214,8 @@ TEST_F(InPlaceResourceRecorderTest, BasicOperationFullHeaders) {
192214
InPlaceResourceRecorder::kFullHeaders, &ok_headers);
193215
recorder->Write(kHello, message_handler());
194216
recorder->Write(kBye, message_handler());
195-
recorder.release()->DoneAndSetHeaders(&ok_headers);
217+
recorder.release()->DoneAndSetHeaders(
218+
&ok_headers, true /* complete response */);
196219

197220
HTTPValue value_out;
198221
ResponseHeaders headers_out;
@@ -216,7 +239,8 @@ TEST_F(InPlaceResourceRecorderTest, DontRemember304) {
216239
scoped_ptr<InPlaceResourceRecorder> recorder(MakeRecorder(kTestUrl));
217240
recorder->ConsiderResponseHeaders(
218241
InPlaceResourceRecorder::kPreliminaryHeaders, &prelim_headers);
219-
recorder.release()->DoneAndSetHeaders(&not_modified_headers);
242+
recorder.release()->DoneAndSetHeaders(
243+
&not_modified_headers, true /* complete response */);
220244

221245
HTTPValue value_out;
222246
ResponseHeaders headers_out;
@@ -237,7 +261,8 @@ TEST_F(InPlaceResourceRecorderTest, Remember500AsFetchFailed) {
237261
scoped_ptr<InPlaceResourceRecorder> recorder(MakeRecorder(kTestUrl));
238262
recorder->ConsiderResponseHeaders(
239263
InPlaceResourceRecorder::kPreliminaryHeaders, &prelim_headers);
240-
recorder.release()->DoneAndSetHeaders(&error_headers);
264+
recorder.release()->DoneAndSetHeaders(
265+
&error_headers, true /* complete response */);
241266

242267
HTTPValue value_out;
243268
ResponseHeaders headers_out;
@@ -252,7 +277,8 @@ TEST_F(InPlaceResourceRecorderTest, RememberEmpty) {
252277

253278
scoped_ptr<InPlaceResourceRecorder> recorder(MakeRecorder(kTestUrl));
254279
// No contents written.
255-
recorder.release()->DoneAndSetHeaders(&ok_headers);
280+
recorder.release()->DoneAndSetHeaders(
281+
&ok_headers, true /* complete response */);
256282

257283
HTTPValue value_out;
258284
ResponseHeaders headers_out;

net/instaweb/system/public/in_place_resource_recorder.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,16 @@ class InPlaceResourceRecorder : public Writer {
109109
// Because of Apache's quirky filter order, we cannot get both the
110110
// uncompressed final contents and the complete headers at the same time.
111111
//
112+
// Set entire_response_received to true if you know that the response data fed
113+
// into Write() is complete. For example, if the browser cancelled the
114+
// download and so this is a partial response, set entire_response_received to
115+
// false so we know not to cache it.
116+
//
112117
// Does not take ownership of response_headers.
113118
//
114119
// Deletes itself. Do not use object after calling DoneAndSetHeaders().
115-
void DoneAndSetHeaders(ResponseHeaders* response_headers);
120+
void DoneAndSetHeaders(ResponseHeaders* response_headers,
121+
bool entire_response_received);
116122

117123
const GoogleString& url() const { return url_; }
118124
MessageHandler* handler() { return handler_; }

0 commit comments

Comments
 (0)