src/ngx_pagespeed.cc
// Header filter to support IPRO.
//
// The control flow here is tricky, probably excessively so.
Header filter to support IPRO.
The control flow here is tricky, probably excessively so.
Header filter to support IPRO . The control flow here is tricky probably excessively so .
ngx_int_t ps_in_place_check_header_filter(ngx_http_request_t* r) {
  ps_request_ctx_t* ctx = ps_get_request_context(r);
  if (ctx == NULL) {
    return ngx_http_next_header_filter(r);
  }
  if (ctx->recorder != NULL) {
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "ps in place check header filter recording: %V", &r->uri);
    CHECK(!ctx->in_place);
     The recorder will do this checking, so pass it the headers.
    ResponseHeaders response_headers;
    copy_response_headers_from_ngx(r, &response_headers);
    ctx->recorder->ConsiderResponseHeaders(
        InPlaceResourceRecorder::kPreliminaryHeaders, &response_headers);
    return ngx_http_next_header_filter(r);
  }
  if (!ctx->in_place) {
    return ngx_http_next_header_filter(r);
  }
   If our request was finalized during the IPRO lookup, we decline.
  if (r->connection->error) {
    return ps_decline_request(r);
  }
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                 "ps in place check header filter initial: %V", &r->uri);
  int status_code = r->headers_out.status;
  bool status_ok = (status_code != 0) && (status_code < 400);
  ps_srv_conf_t* cfg_s = ps_get_srv_config(r);
  NgxServerContext* server_context = cfg_s->server_context;
  MessageHandler* message_handler = cfg_s->handler;
  GoogleString url = ps_determine_url(r);
   The URL we use for cache key is a bit different since it may
   have PageSpeed query params removed.
  GoogleString cache_url = ctx->url_string;
   continue process
  if (status_ok) {
    ctx->in_place = false;
    server_context->rewrite_stats()->ipro_served()->Add(1);
    message_handler->Message(
        kInfo, "Serving rewritten resource in-place: %s",
        url.c_str());
    return ngx_http_next_header_filter(r);
  }
  if (status_code == CacheUrlAsyncFetcher::kNotInCacheStatus &&
      !r->header_only) {
    server_context->rewrite_stats()->ipro_not_in_cache()->Add(1);
    server_context->message_handler()->Message(
        kInfo,
        "Could not rewrite resource in-place "
        "because URL is not in cache: %s",
        cache_url.c_str());
    const SystemRewriteOptions* options = SystemRewriteOptions::DynamicCast(
        ctx->driver->options());
    RequestContextPtr request_context(
        cfg_s->server_context->NewRequestContext(r));
    request_context->set_options(options->ComputeHttpOptions());
    RequestHeaders request_headers;
    copy_request_headers_from_ngx(r, &request_headers);
     This URL was not found in cache (neither the input resource nor
     a ResourceNotCacheable entry) so we need to get it into cache
     (or at least a note that it cannot be cached stored there).
     We do that using an Apache output filter.
    ctx->recorder = new InPlaceResourceRecorder(
        request_context,
        cache_url,
        ctx->driver->CacheFragment(),
        request_headers.GetProperties(),
        options->ipro_max_response_bytes(),
        options->ipro_max_concurrent_recordings(),
        server_context->http_cache(),
        server_context->statistics(),
        message_handler);
     set in memory flag for in_place_body_filter
    r->filter_need_in_memory = 1;
     We don't have the response headers at all yet because we haven't yet gone
     to the backend.
  } else {
    server_context->rewrite_stats()->ipro_not_rewritable()->Add(1);
    message_handler->Message(
        kInfo, "Could not rewrite resource in-place: %s", url.c_str());
  }
  return ps_decline_request(r);
}
ngx_int_t ps_in_place_check_header_filter ( ngx_http_request_t * r ) { ps_request_ctx_t * ctx = ps_get_request_context ( r ) ; if ( ctx == NULL ) { return ngx_http_next_header_filter ( r ) ; } if ( ctx -> recorder != NULL ) { ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , " " , & r -> uri ) ; CHECK ( ! ctx -> in_place ) ; ResponseHeaders response_headers ; copy_response_headers_from_ngx ( r , & response_headers ) ; ctx -> recorder -> ConsiderResponseHeaders ( InPlaceResourceRecorder :: kPreliminaryHeaders , & response_headers ) ; return ngx_http_next_header_filter ( r ) ; } if ( ! ctx -> in_place ) { return ngx_http_next_header_filter ( r ) ; } if ( r -> connection -> error ) { return ps_decline_request ( r ) ; } ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , " " , & r -> uri ) ; int status_code = r -> headers_out . status ; bool status_ok = ( status_code != 0 ) && ( status_code < 400 ) ; ps_srv_conf_t * cfg_s = ps_get_srv_config ( r ) ; NgxServerContext * server_context = cfg_s -> server_context ; MessageHandler * message_handler = cfg_s -> handler ; GoogleString url = ps_determine_url ( r ) ; GoogleString cache_url = ctx -> url_string ; if ( status_ok ) { ctx -> in_place = false ; server_context -> rewrite_stats ( ) -> ipro_served ( ) -> Add ( 1 ) ; message_handler -> Message ( kInfo , " " , url . c_str ( ) ) ; return ngx_http_next_header_filter ( r ) ; } if ( status_code == CacheUrlAsyncFetcher :: kNotInCacheStatus && ! r -> header_only ) { server_context -> rewrite_stats ( ) -> ipro_not_in_cache ( ) -> Add ( 1 ) ; server_context -> message_handler ( ) -> Message ( kInfo , " " " " , cache_url . c_str ( ) ) ; const SystemRewriteOptions * options = SystemRewriteOptions :: DynamicCast ( ctx -> driver -> options ( ) ) ; RequestContextPtr request_context ( cfg_s -> server_context -> NewRequestContext ( r ) ) ; request_context -> set_options ( options -> ComputeHttpOptions ( ) ) ; RequestHeaders request_headers ; copy_request_headers_from_ngx ( r , & request_headers ) ; ctx -> recorder = new InPlaceResourceRecorder ( request_context , cache_url , ctx -> driver -> CacheFragment ( ) , request_headers . GetProperties ( ) , options -> ipro_max_response_bytes ( ) , options -> ipro_max_concurrent_recordings ( ) , server_context -> http_cache ( ) , server_context -> statistics ( ) , message_handler ) ; r -> filter_need_in_memory = 1 ; } else { server_context -> rewrite_stats ( ) -> ipro_not_rewritable ( ) -> Add ( 1 ) ; message_handler -> Message ( kInfo , " " , url . c_str ( ) ) ; } return ps_decline_request ( r ) ; }
Header filter to support IPRO.
Header filter to support IPRO .
// We didn't find this resource in cache originally, so we're recording it // as it passes us by.  At this point the headers from things that run // before us are set but not things that run after us, which means here is // where we need to check whether there's a "Content-Encoding: gzip".  If we // waited to do this in ps_in_place_body_filter we wouldn't be able to tell // the difference between response headers that have "C-E: gz" because we're // proxying for an upstream that gzipped the content and response headers // that have it because the gzip filter (which runs after us) is going to // produce gzipped output. // // The recorder will do this checking, so pass it the headers. // If our request was finalized during the IPRO lookup, we decline. // The URL we use for cache key is a bit different since it may // have PageSpeed query params removed. // continue process // This URL was not found in cache (neither the input resource nor // a ResourceNotCacheable entry) so we need to get it into cache // (or at least a note that it cannot be cached stored there). // We do that using an Apache output filter. // set in memory flag for in_place_body_filter // We don't have the response headers at all yet because we haven't yet gone // to the backend.