@@ -128,7 +128,7 @@ InstawebHandler::~InstawebHandler() {
128128 // If fetch_ is null we either never tried to fetch anything or it took
129129 // ownership of itself after timing out.
130130 if (fetch_ != NULL ) {
131- if (WaitForFetch () == ApacheFetch:: kWaitSuccess ) {
131+ if (WaitForFetch ()) {
132132 delete fetch_; // Fetch completed normally.
133133 } else {
134134 // Fetch took ownership of itself and will continue in the background.
@@ -137,19 +137,19 @@ InstawebHandler::~InstawebHandler() {
137137 }
138138}
139139
140- ApacheFetch::WaitResult InstawebHandler::WaitForFetch () {
140+ bool InstawebHandler::WaitForFetch () {
141141 if (fetch_ == NULL ) {
142- return ApacheFetch:: kWaitSuccess ; // Nothing to wait for.
142+ return true ; // Nothing to wait for.
143143 }
144144
145- ApacheFetch::WaitResult wait_result = fetch_->Wait (rewrite_driver_);
146- if (wait_result != ApacheFetch:: kWaitSuccess ) {
145+ bool ok = fetch_->Wait (rewrite_driver_);
146+ if (!ok ) {
147147 // Give up on waiting for the fetch so we stop tying up a thread. Fetch has
148148 // taken ownership of itself, will discard any messages it receives if it's
149149 // abandoned, and will delete itself when Done() is called, if ever.
150150 fetch_ = NULL ;
151151 }
152- return wait_result ;
152+ return ok ;
153153}
154154
155155void InstawebHandler::SetupSpdyConnectionIfNeeded () {
@@ -179,16 +179,19 @@ RewriteDriver* InstawebHandler::MakeDriver() {
179179}
180180
181181ApacheFetch* InstawebHandler::MakeFetch (const GoogleString& url,
182+ bool buffered,
182183 StringPiece debug_info) {
183184 DCHECK (fetch_ == NULL );
184185 // ApacheFetch takes ownership of request_headers.
185186 RequestHeaders* request_headers = new RequestHeaders ();
186187 ApacheRequestToRequestHeaders (*request_, request_headers);
187- fetch_ = new ApacheFetch (url, debug_info, server_context_->thread_system (),
188- server_context_->timer (),
189- new ApacheWriter (request_),
190- request_headers, request_context_, options_,
191- server_context_->message_handler ());
188+ fetch_ = new ApacheFetch (
189+ url, debug_info, server_context_->thread_system (),
190+ server_context_->timer (),
191+ new ApacheWriter (request_, server_context_->thread_system ()),
192+ request_headers, request_context_, options_,
193+ server_context_->message_handler ());
194+ fetch_->set_buffered (buffered);
192195 return fetch_;
193196}
194197
@@ -441,13 +444,12 @@ bool InstawebHandler::HandleAsInPlace() {
441444 != NULL ) || (request_->user != NULL ));
442445
443446 RewriteDriver* driver = MakeDriver ();
444- MakeFetch (original_url_ , " ipro" );
447+ MakeFetch (true /* buffered */ , " ipro" );
445448 fetch_->set_handle_error (false );
446449 driver->FetchInPlaceResource (stripped_gurl_, false /* proxy_mode */ , fetch_);
447- ApacheFetch::WaitResult wait_result = WaitForFetch ();
448- if (wait_result != ApacheFetch::kWaitSuccess ) {
449- // Note: fetch_ has been released; no longer safe to look at;
450- handled = (wait_result == ApacheFetch::kAbandonedAndHandled );
450+ bool ok = WaitForFetch ();
451+ if (!ok) {
452+ // Nothing to do, fetch_ has been released, no longer safe to look at.
451453 } else if (fetch_->status_ok ()) {
452454 server_context_->rewrite_stats ()->ipro_served ()->Add (1 );
453455 handled = true ;
@@ -504,12 +506,12 @@ bool InstawebHandler::HandleAsProxy() {
504506 &host_header, &is_proxy) &&
505507 is_proxy) {
506508 RewriteDriver* driver = MakeDriver ();
507- MakeFetch (mapped_url, " proxy" );
509+ MakeFetch (mapped_url, true /* buffered */ , " proxy" );
508510 fetch_->set_is_proxy (true );
509511 driver->SetRequestHeaders (*fetch_->request_headers ());
510512 server_context_->proxy_fetch_factory ()->StartNewProxyFetch (
511513 mapped_url, fetch_, driver, NULL , NULL );
512- handled = WaitForFetch () != ApacheFetch:: kAbandonedAndDeclined ;
514+ handled = WaitForFetch ();
513515 }
514516
515517 return handled; // false == declined
@@ -867,39 +869,51 @@ apr_status_t InstawebHandler::instaweb_handler(request_rec* request) {
867869 server_context->StatisticsPage (is_global_statistics,
868870 instaweb_handler.query_params (),
869871 instaweb_handler.options (),
870- instaweb_handler.MakeFetch (" statistics" ));
872+ instaweb_handler.MakeFetch (
873+ false /* unbuffered */ , " statistics" ));
871874 return OK;
872875 } else if ((request_handler_str == kAdminHandler ) ||
873876 (request_handler_str == kGlobalAdminHandler )) {
874877 InstawebHandler instaweb_handler (request);
878+ // The fetch has to be buffered because if it's a cache lookup it could
879+ // complete asynchrously via the rewrite thread.
875880 server_context->AdminPage ((request_handler_str == kGlobalAdminHandler ),
876881 instaweb_handler.stripped_gurl (),
877882 instaweb_handler.query_params (),
878883 instaweb_handler.options (),
879- instaweb_handler.MakeFetch (" admin" ));
884+ instaweb_handler.MakeFetch (
885+ true /* buffered */ , " admin" ));
880886 ret = OK;
881887 } else if (global_config->enable_cache_purge () &&
882888 !global_config->purge_method ().empty () &&
883889 (global_config->purge_method () == request->method )) {
884890 InstawebHandler instaweb_handler (request);
885891 AdminSite* admin_site = server_context->admin_site ();
892+ // I'm not convinced that the purge handler must complete synchronously. It
893+ // schedules work on the rewrite driver factory's scheduler, and while in my
894+ // testing it processes everything on the calling thread I'm not sure this
895+ // is part of the contract. The response is just headers and a few bytes of
896+ // body, so buffering is basically free. To be on the safe side let's
897+ // buffer this one too.
886898 admin_site->PurgeHandler (instaweb_handler.original_url_ ,
887899 server_context->cache_path (),
888- instaweb_handler.MakeFetch (" purge" ));
900+ instaweb_handler.MakeFetch (
901+ true /* buffered */ , " purge" ));
889902 ret = OK;
890903 } else if (request_handler_str == kConsoleHandler ) {
891904 InstawebHandler instaweb_handler (request);
892905 server_context->ConsoleHandler (*instaweb_handler.options (),
893906 AdminSite::kOther ,
894907 instaweb_handler.query_params (),
895- instaweb_handler.MakeFetch (" console" ));
908+ instaweb_handler.MakeFetch (
909+ false /* unbuffered */ , " console" ));
896910 ret = OK;
897911 } else if (request_handler_str == kMessageHandler ) {
898912 InstawebHandler instaweb_handler (request);
899913 server_context->MessageHistoryHandler (
900914 *instaweb_handler.options (),
901915 AdminSite::kOther ,
902- instaweb_handler.MakeFetch (" messages" ));
916+ instaweb_handler.MakeFetch (false /* unbuffered */ , " messages" ));
903917 ret = OK;
904918 } else if (request_handler_str == kLogRequestHeadersHandler ) {
905919 // For testing CustomFetchHeader.
0 commit comments