src/ngx_pagespeed.cc
// After pagespeed has had a chance to run, copy the headers it produced to
// nginx so it can send them out to the browser.
After pagespeed has had a chance to run, copy the headers it produced to
nginx so it can send them out to the browser.
After pagespeed has had a chance to run copy the headers it produced to nginx so it can send them out to the browser .
ngx_int_t ps_html_rewrite_header_filter(ngx_http_request_t* r) {
  ps_srv_conf_t* cfg_s = ps_get_srv_config(r);
  if (ps_disabled(cfg_s)) {
    return ngx_http_next_header_filter(r);
  }
  if (r != r->main) {
    return ngx_http_next_header_filter(r);
  }
  cfg_s->server_context->FlushCacheIfNecessary();
  ps_request_ctx_t* ctx = ps_get_request_context(r);
  if (ctx == NULL || ctx->html_rewrite == false) {
    return ngx_http_next_header_filter(r);
  }
  if (r->err_status != 0) {
    ctx->html_rewrite = false;
    return ngx_http_next_header_filter(r);
  }
  ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                 "http pagespeed html rewrite header filter \"%V\"", &r->uri);
  const ContentType* content_type =
      MimeTypeToContentType(
          str_to_string_piece(r->headers_out.content_type));
  if (content_type == NULL || !content_type->IsHtmlLike()) {
    ctx->html_rewrite = false;
    return ngx_http_next_header_filter(r);
  }
  ngx_int_t rc = ps_resource_handler(r, true ,
                                     RequestRouting::kResource);
  if (rc != NGX_OK) {
    ctx->html_rewrite = false;
    return ngx_http_next_header_filter(r);
  }
  if (r->headers_out.content_encoding &&
      r->headers_out.content_encoding->value.len) {
    if (!ps_has_stacked_content_encoding(r)) {
      StringPiece content_encoding =
          str_to_string_piece(r->headers_out.content_encoding->value);
      GzipInflater::InflateType inflate_type = GzipInflater::kGzip;
      bool is_encoded = false;
      if (StringCaseEqual(content_encoding, "deflate")) {
        is_encoded = true;
        inflate_type = GzipInflater::kDeflate;
      } else if (StringCaseEqual(content_encoding, "gzip")) {
        is_encoded = true;
      }
      if (is_encoded) {
        r->headers_out.content_encoding->hash = 0;
        r->headers_out.content_encoding = NULL;
        ctx->inflater_ = new GzipInflater(inflate_type);
        ctx->inflater_->Init();
      }
    }
  }
  ps_strip_html_headers(r);
  ctx->location_field_set = r->headers_out.location != NULL;
  copy_response_headers_from_ngx(r, ctx->base_fetch->response_headers());
  ps_set_buffered(r, true);
  r->filter_need_in_memory = 1;
  return NGX_AGAIN;
}
ngx_int_t ps_html_rewrite_header_filter ( ngx_http_request_t * r ) { ps_srv_conf_t * cfg_s = ps_get_srv_config ( r ) ; if ( ps_disabled ( cfg_s ) ) { return ngx_http_next_header_filter ( r ) ; } if ( r != r -> main ) { return ngx_http_next_header_filter ( r ) ; } cfg_s -> server_context -> FlushCacheIfNecessary ( ) ; ps_request_ctx_t * ctx = ps_get_request_context ( r ) ; if ( ctx == NULL || ctx -> html_rewrite == false ) { return ngx_http_next_header_filter ( r ) ; } if ( r -> err_status != 0 ) { ctx -> html_rewrite = false ; return ngx_http_next_header_filter ( r ) ; } ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r -> connection -> log , 0 , " \" \" " , & r -> uri ) ; const ContentType * content_type = MimeTypeToContentType ( str_to_string_piece ( r -> headers_out . content_type ) ) ; if ( content_type == NULL || ! content_type -> IsHtmlLike ( ) ) { ctx -> html_rewrite = false ; return ngx_http_next_header_filter ( r ) ; } ngx_int_t rc = ps_resource_handler ( r , true , RequestRouting :: kResource ) ; if ( rc != NGX_OK ) { ctx -> html_rewrite = false ; return ngx_http_next_header_filter ( r ) ; } if ( r -> headers_out . content_encoding && r -> headers_out . content_encoding -> value . len ) { if ( ! ps_has_stacked_content_encoding ( r ) ) { StringPiece content_encoding = str_to_string_piece ( r -> headers_out . content_encoding -> value ) ; GzipInflater :: InflateType inflate_type = GzipInflater :: kGzip ; bool is_encoded = false ; if ( StringCaseEqual ( content_encoding , " " ) ) { is_encoded = true ; inflate_type = GzipInflater :: kDeflate ; } else if ( StringCaseEqual ( content_encoding , " " ) ) { is_encoded = true ; } if ( is_encoded ) { r -> headers_out . content_encoding -> hash = 0 ; r -> headers_out . content_encoding = NULL ; ctx -> inflater_ = new GzipInflater ( inflate_type ) ; ctx -> inflater_ -> Init ( ) ; } } } ps_strip_html_headers ( r ) ; ctx -> location_field_set = r -> headers_out . location != NULL ; copy_response_headers_from_ngx ( r , ctx -> base_fetch -> response_headers ( ) ) ; ps_set_buffered ( r , true ) ; r -> filter_need_in_memory = 1 ; return NGX_AGAIN ; }
After pagespeed has had a chance to run, copy the headers it produced to
nginx so it can send them out to the browser.
After pagespeed has had a chance to run copy the headers it produced to nginx so it can send them out to the browser .
// Don't handle subrequests. // Poll for cache flush on every request (polls are rate-limited). // We don't know what this request is, but we only want to send html through // to pagespeed.  Check the content type header and find out. // Unknown or otherwise non-html content type: skip it. /* html rewrite */ // headers_out.content_encoding will be set to the exact last // Content-Encoding response header value that nginx receives. To // check if there were multiple (aka stacked) encodings in the // response headers, we must iterate them all. // See https://github.com/apache/incubator-pagespeed-ngx/issues/819 // TODO(jefftk): is this thread safe?