Make sure http requests to css/js files work correctly.

Paramètres

array $requirements: Array of requirements used in hook_requirements().

array $urls: Array of urls.

array $options: Options array to pass to drupal_http_request().

bool $mod_url: Set to TRUE if an alt URL was used.

string $type: String: css or js.

string $url_path: The url path to the file.

string $file_path: File path to the file.

string $filename: Name of the file.

1 call to advagg_install_chk_urls()
advagg_install_check_via_http dans ./advagg.install
Make sure http requests to css/js files work correctly.

Fichier

./advagg.install, line 1808

Code

function advagg_install_chk_urls(array &$requirements, array $urls, array $options, $mod_url, $type, $url_path, $file_path, $filename) {
    // Ensure translations don't break at install time.
    $t = get_t();
    list($css_path, $js_path) = advagg_get_root_files_dir();
    $config_path = advagg_admin_config_root_path();
    $options += array(
        'timeout' => 8,
    );
    $is_apache = FALSE;
    if (stripos($_SERVER['SERVER_SOFTWARE'], 'apache') !== FALSE || function_exists('apache_get_modules')) {
        $is_apache = TRUE;
        $mod_headers = advagg_install_apache_mod_loaded('mod_headers');
        $mod_rewrite = advagg_install_apache_mod_loaded('mod_rewrite');
        $mod_expires = advagg_install_apache_mod_loaded('mod_expires');
    }
    foreach ($urls as $url) {
        $key = strtolower(pathinfo($url, PATHINFO_EXTENSION));
        // Make sure the URL contains a schema.
        if (strpos($url, 'http') !== 0) {
            if ($GLOBALS['is_https']) {
                $url = 'https:' . $url;
            }
            else {
                $url = 'http:' . $url;
            }
        }
        // Before sending the request when using s3fs, check if the file exists.
        if (module_exists('s3fs') && !file_exists($url_path . '/' . $filename)) {
            if (module_exists('httprl') && variable_get('advagg_use_httprl', ADVAGG_USE_HTTPRL)) {
                $httprl_message = 'This may be due to an issue with the HTTPRL module or its configuration. ';
            }
            else {
                $httprl_message = '';
            }
            $requirements['advagg_' . $type . '_missing' . $key] = array(
                'title' => $t('Adv CSS/JS Agg - file does not exist'),
                'severity' => REQUIREMENT_WARNING,
                'value' => $t('Unable to find %type files.', array(
                    '%type' => $type,
                )),
                'description' => $t('The AdvAgg database records and S3 files are not in sync. The file referenced in the database to perform a test cannot be found in the S3 file system. @httprl_messageFile URL: <pre>@file</pre>', array(
                    '@httprl_message' => $httprl_message,
                    '@file' => $url,
                )),
            );
            continue;
        }
        // Send request.
        advagg_install_url_mod($url, $options, $mod_url);
        $request = drupal_http_request($url, $options);
        $encoding_type = 'gzip';
        if (!empty($request->options['headers']['Accept-Encoding']) && strpos($request->options['headers']['Accept-Encoding'], 'br') !== FALSE) {
            $encoding_type = 'br';
        }
        if (!variable_get('advagg_skip_gzip_check', ADVAGG_SKIP_GZIP_CHECK)) {
            // Try again on a code 0.
            if ($request->code == 0) {
                $request = drupal_http_request($url, $options);
                $encoding_type = 'gzip';
                if (!empty($request->options['headers']['Accept-Encoding']) && strpos($request->options['headers']['Accept-Encoding'], 'br') !== FALSE) {
                    $encoding_type = 'br';
                }
            }
            // Check response. Report an error if
            // - Not a 200.
            // - Headers do not contain "content-encoding".
            // - content-encoding is not gzip, deflate or br.
            if ($request->code != 200 || empty($request->headers['content-encoding']) || $request->headers['content-encoding'] !== 'gzip' && $request->headers['content-encoding'] !== 'deflate' && $request->headers['content-encoding'] !== 'br') {
                // Gzip failed.
                if (!variable_get('advagg_gzip', ADVAGG_GZIP) && $encoding_type === 'gzip') {
                    // Recommend that gzip be turned on.
                    $requirements['advagg_' . $type . '_gzip' . $key] = array(
                        'title' => $t('Adv CSS/JS Agg - gzip'),
                        'severity' => REQUIREMENT_WARNING,
                        'value' => $t('Gzip is failing for %type files.', array(
                            '%type' => $type,
                        )),
                        'description' => $t('Try enabling on the "Create .gz files" setting on the <a href="@advagg">Advanced CSS/JS Aggregation Configuration page</a>', array(
                            '@advagg' => url($config_path . '/advagg'),
                            '%type' => $type,
                        )),
                    );
                }
                elseif (function_exists('brotli_compress') && defined('BROTLI_TEXT') && !variable_get('advagg_brotli', ADVAGG_BROTLI) && $encoding_type === 'br') {
                    // Recommend that br be turned on.
                    $requirements['advagg_' . $type . '_br' . $key] = array(
                        'title' => $t('Adv CSS/JS Agg - brotli'),
                        'severity' => REQUIREMENT_WARNING,
                        'value' => $t('Brotli is failing for %type files.', array(
                            '%type' => $type,
                        )),
                        'description' => $t('Try enabling on the "Create .br files" setting on the <a href="@advagg">Advanced CSS/JS Aggregation Configuration page</a>', array(
                            '@advagg' => url($config_path . '/advagg'),
                            '%type' => $type,
                        )),
                    );
                }
                else {
                    // If not apache skip this.
                    $apache_module_missing = FALSE;
                    if ($is_apache) {
                        if ($mod_headers === FALSE || $mod_rewrite === FALSE) {
                            $apache_module_missing = TRUE;
                            if ($mod_headers === FALSE) {
                                $requirements['advagg_mod_headers' . $key . '_' . $encoding_type] = array(
                                    'title' => $t('Adv CSS/JS Agg - Apache'),
                                    'description' => $t('The Apache module "mod_headers" is not available. Enable <a href="!link">mod_headers</a> for Apache if at all possible. This is causing @encoding to fail.', array(
                                        '!link' => 'http://httpd.apache.org/docs/current/mod/mod_headers.html',
                                        '@encoding' => $encoding_type,
                                    )),
                                    'severity' => REQUIREMENT_WARNING,
                                    'value' => $t('Apache module "mod_headers" is not installed.'),
                                );
                            }
                            if ($mod_rewrite === FALSE) {
                                $requirements['advagg_mod_rewrite' . $key . '_' . $encoding_type] = array(
                                    'title' => $t('Adv CSS/JS Agg - Apache'),
                                    'description' => $t('The Apache module "mod_rewrite" is not available.  You must enable <a href="!link">mod_rewrite</a> for Apache. This is causing @encoding to fail.', array(
                                        '!link' => 'http://httpd.apache.org/docs/current/mod/mod_rewrite.html',
                                        '@encoding' => $encoding_type,
                                    )),
                                    'severity' => REQUIREMENT_ERROR,
                                    'value' => $t('Apache module "mod_rewrite" is not installed.'),
                                );
                            }
                        }
                    }
                    if (!$apache_module_missing) {
                        // Check via external service.
                        $ext_url = 'http://checkgzipcompression.com/?url=' . urlencode($url);
                        if ($encoding_type === 'br') {
                            $ext_url = 'https://tools.keycdn.com/brotli-query.php?url=' . urlencode($url) . '&public=0';
                        }
                        $external_compression_request = drupal_http_request($ext_url, array(
                            'timeout' => 7,
                            'headers' => array(
                                'Connection' => 'close',
                            ),
                        ));
                        if (!empty($external_compression_request->data)) {
                            if ($encoding_type === 'br') {
                                if (stripos($external_compression_request->data, '<strong>') !== FALSE) {
                                    preg_match("/<strong>(.*)<\\/strong>/siU", $external_compression_request->data, $title_matches);
                                    if (stripos($title_matches[1], 'Negative') === FALSE) {
                                        $external_test_results = 1;
                                    }
                                    else {
                                        $external_test_results = -1;
                                    }
                                }
                                else {
                                    $external_test_results = 0;
                                }
                            }
                            elseif (stripos($external_compression_request->data, '<title>') !== FALSE) {
                                preg_match("/<title>(.*)<\\/title>/siU", $external_compression_request->data, $title_matches);
                                if (stripos($title_matches[1], 'gzip') === FALSE) {
                                    $external_test_results = 0;
                                }
                                elseif (stripos($title_matches[1], 'not gzip') === FALSE) {
                                    $external_test_results = 1;
                                }
                                else {
                                    $external_test_results = -1;
                                }
                            }
                        }
                        if (!isset($external_test_results) || $external_test_results !== 1) {
                            if ($request->code != 200) {
                                $rewritebase = advagg_htaccess_rewritebase();
                                if (!empty($rewritebase)) {
                                    if ($type === 'css') {
                                        $rewritebase_advagg = advagg_htaccess_rewritebase($css_path[1]);
                                    }
                                    if ($type === 'js') {
                                        $rewritebase_advagg = advagg_htaccess_rewritebase($js_path[1]);
                                    }
                                }
                                $advagg_htaccess_rewritebase = variable_get('advagg_htaccess_rewritebase', ADVAGG_HTACCESS_REWRITEBASE);
                                if ($request->code == 307 && !empty($rewritebase) && empty($rewritebase_advagg) && empty($advagg_htaccess_rewritebase)) {
                                    $requirements['advagg_' . $type . $encoding_type . $key . $options['version']] = array(
                                        'title' => $t('Adv CSS/JS Agg - @encoding', array(
                                            '@encoding' => $encoding_type,
                                        )),
                                        'severity' => REQUIREMENT_WARNING,
                                        'value' => $t('@encoding is failing for %type files.', array(
                                            '%type' => $type,
                                            '@encoding' => $encoding_type,
                                        )),
                                        'description' => $t('The web server is not returning a 200, instead a @code is being returned. The RewriteBase option should be set on the <a href="@url">configuration page</a> under "Obscure Options" look for "AdvAgg RewriteBase Directive in .htaccess files". Raw request info: <pre>@request</pre>', array(
                                            '@code' => $request->code,
                                            '@encoding' => $encoding_type,
                                            '@request' => print_r($request, TRUE),
                                            '@url' => url($config_path . '/advagg', array(
                                                'fragment' => 'edit-advagg-htaccess-rewritebase',
                                            )),
                                        )),
                                    );
                                }
                                else {
                                    if (module_exists('s3fs') && ($request->code == 307 || $request->code == -2)) {
                                        $requirements['advagg_' . $type . $encoding_type . $key . $options['version']] = array(
                                            'title' => $t('Adv CSS/JS Agg - Redirect Loop'),
                                            'severity' => REQUIREMENT_WARNING,
                                            'value' => $t('S3fs issue. Proxy is not setup correctly for %type.', array(
                                                '%type' => $type,
                                            )),
                                            'description' => $t('The web server is not returning a 200, instead a @code is being returned. Apache proxy settings for httpd.conf: <p><code>!httpd</code></p>. Raw request info: <pre>@request</pre>', array(
                                                '!httpd' => nl2br(str_replace('  ', '&nbsp;&nbsp;', htmlentities(advagg_install_s3fs_proxy_settings($type)))),
                                                '@code' => $request->code,
                                                '@encoding' => $encoding_type,
                                                '@request' => print_r($request, TRUE),
                                            )),
                                        );
                                    }
                                    else {
                                        $requirements['advagg_' . $type . $encoding_type . $key . $options['version']] = array(
                                            'title' => $t('Adv CSS/JS Agg - @encoding', array(
                                                '@encoding' => $encoding_type,
                                            )),
                                            'severity' => REQUIREMENT_WARNING,
                                            'value' => $t('@encoding is failing for %type files.', array(
                                                '%type' => $type,
                                                '@encoding' => $encoding_type,
                                            )),
                                            'description' => $t('The web server is not returning a 200, instead a @code is being returned. @encoding can not be tested. Raw request info: <pre>@request</pre>', array(
                                                '@code' => $request->code,
                                                '@encoding' => $encoding_type,
                                                '@request' => print_r($request, TRUE),
                                            )),
                                        );
                                    }
                                }
                            }
                            elseif (empty($request->data)) {
                                $url = 'http://checkgzipcompression.com/?url=' . urlencode($url);
                                if ($encoding_type === 'br') {
                                    $url = 'https://tools.keycdn.com/brotli-query.php?url=' . urlencode($url) . '&public=0';
                                }
                                $requirements['advagg_' . $type . $encoding_type . $key . $options['version']] = array(
                                    'title' => $t('Adv CSS/JS Agg - @encoding', array(
                                        '@encoding' => $encoding_type,
                                    )),
                                    'severity' => REQUIREMENT_WARNING,
                                    'value' => $t('@encoding is failing for %type files.', array(
                                        '%type' => $type,
                                        '@encoding' => $encoding_type,
                                    )),
                                    'description' => $t('No data was returned from your server; this @encoding test can not be done locally. Error: @error - @message You can manually test if @encoding is working by <a href="@urlGZ">going here</a> and seeing if @encoding is enabled. You can turn this warning off by adding this to your settings.php file: <code>@skipcode</code>', array(
                                        '@error' => $request->code,
                                        '@message' => isset($request->error) ? $request->error : '',
                                        '@url' => $url,
                                        '@skipcode' => '$conf[\'advagg_skip_gzip_check\'] = TRUE;',
                                        '@encoding' => $encoding_type,
                                    )),
                                );
                            }
                            else {
                                // Recommend servers configuration be adjusted.
                                $request->data = '...';
                                $requirements['advagg_' . $type . $encoding_type . $key . $options['version']] = array(
                                    'title' => $t('Adv CSS/JS Agg - @encoding', array(
                                        '@encoding' => $encoding_type,
                                    )),
                                    'severity' => REQUIREMENT_WARNING,
                                    'value' => $t('@encoding is failing for %type files.', array(
                                        '%type' => $type,
                                        '@encoding' => $encoding_type,
                                    )),
                                    'description' => $t('The web servers configuration will need to be adjusted. In most cases make sure that the webroots .htaccess file still contains this section "Rules to correctly serve gzip compressed CSS and JS files". Also check in the <a href="@readme">readme</a>, under Troubleshooting. Certain default web server configurations (<a href="!nginx">nginx</a>) do not gzip HTTP/1.0 requests. If you are using cloudfront you will have to <a href="!cloudfront">add metadata</a> to the .gz files. There are some other options if using <a href="!so">cloudfront</a>. Raw request info: <pre>@request</pre>', array(
                                        '!nginx' => 'http://www.cdnplanet.com/blog/gzip-nginx-cloudfront/',
                                        '@request' => print_r($request, TRUE),
                                        '!cloudfront' => 'http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ServingCompressedFiles.html#CompressedS3',
                                        '!so' => 'http://stackoverflow.com/questions/5442011/serving-gzipped-css-and-javascript-from-amazon-cloudfront-via-s3',
                                        '@readme' => url(drupal_get_path('module', 'advagg') . '/README.txt'),
                                    )),
                                );
                            }
                        }
                    }
                }
            }
            elseif ($request->code == 200 && !empty($request->headers['content-encoding']) && !empty($request->data) && ($request->headers['content-encoding'] === 'gzip' || $request->headers['content-encoding'] === 'deflate' || $request->headers['content-encoding'] === 'br')) {
                // Do the first level of decoding if not already done.
                if (!isset($request->chunk_size)) {
                    if ($request->headers['content-encoding'] === 'gzip') {
                        $request->data = @gzinflate(substr($request->data, 10));
                    }
                    elseif ($request->headers['content-encoding'] === 'deflate') {
                        $request->data = @gzinflate($request->data);
                    }
                    elseif ($request->headers['content-encoding'] === 'br' && is_callable('brotli_uncompress')) {
                        $request->data = @brotli_uncompress($request->data);
                    }
                }
                // Check for double gzip compression.
                $contents = @file_get_contents($options['#advagg_path']);
                if ($contents !== $request->data && (@gzinflate(substr($request->data, 10)) !== FALSE || @gzinflate($request->data) !== FALSE)) {
                    $config_path = advagg_admin_config_root_path();
                    $description = '';
                    if (variable_get('advagg_gzip', ADVAGG_GZIP)) {
                        $description .= $t('Go to the Advanced CSS/JS aggregation <a href="@settings">settings page</a>, under Obsucre Options uncheck the Create .gz files setting.', array(
                            '@settings' => url($config_path . '/advagg', array(
                                'fragment' => 'edit-obscure',
                            )),
                        ));
                    }
                    else {
                        $description .= $t('Your webserver configuration needs to be changed so that %type files are not being double compressed.', array(
                            '%type' => $type,
                        ));
                        if (isset($request->headers['content-type'])) {
                            $description .= ' ' . $t('The content type is: %type.', array(
                                '%type' => $request->headers['content-type'],
                            ));
                        }
                    }
                    $requirements['advagg_' . $type . '_gzip' . $key . $options['version']] = array(
                        'title' => $t('Adv CSS/JS Agg - gzip'),
                        'severity' => REQUIREMENT_ERROR,
                        'value' => $t('Double gzip encoding detected for %type files.', array(
                            '%type' => $type,
                        )),
                        'description' => $description,
                    );
                }
                if ($contents !== $request->data && (is_callable('brotli_uncompress') && @brotli_uncompress($request->data) !== FALSE)) {
                    $config_path = advagg_admin_config_root_path();
                    $description = '';
                    if (variable_get('advagg_brotli', ADVAGG_BROTLI)) {
                        $description .= $t('Go to the Advanced CSS/JS aggregation <a href="@settings">settings page</a>, under Obsucre Options uncheck the Create .br files setting.', array(
                            '@settings' => url($config_path . '/advagg', array(
                                'fragment' => 'edit-obscure',
                            )),
                        ));
                    }
                    else {
                        $description .= $t('Your webserver configuration needs to be changed so that %type files are not being double compressed.', array(
                            '%type' => $type,
                        ));
                        if (isset($request->headers['content-type'])) {
                            $description .= ' ' . $t('The content type is: %type.', array(
                                '%type' => $request->headers['content-type'],
                            ));
                        }
                    }
                    $requirements['advagg_' . $type . '_br' . $key . $options['version']] = array(
                        'title' => $t('Adv CSS/JS Agg - br'),
                        'severity' => REQUIREMENT_ERROR,
                        'value' => $t('Double br encoding detected for %type files.', array(
                            '%type' => $type,
                        )),
                        'description' => $description,
                    );
                }
            }
        }
        $content_type = $type;
        if ($content_type === 'js') {
            $content_type = 'javascript';
        }
        if ($request->code == 200) {
            $matches = array();
            if (!empty($request->headers['x-advagg']) && preg_match('/Generated file at (\\d+)/is', $request->headers['x-advagg'], $matches) && $matches[1] + 30 > REQUEST_TIME) {
                if (!file_exists($file_path . '/' . $filename)) {
                    $requirements['advagg_' . $type . '_file_write_' . $key] = array(
                        'title' => $t('Adv CSS/JS Agg - Can not write to the filesystem'),
                        'severity' => REQUIREMENT_ERROR,
                        'value' => $t('The request for a file was served by Drupal instead of the web server (like Apache).'),
                        'description' => $t('Something is preventing writes to your filesystem from working.'),
                    );
                }
                else {
                    $requirements['advagg_' . $type . '_loopback_issue' . $key] = array(
                        'title' => $t('Adv CSS/JS Agg - Incorrect readings'),
                        'severity' => REQUIREMENT_WARNING,
                        'value' => $t('The request for a file was served by Drupal instead of the web server (like Apache).'),
                        'description' => $t('It means that AdvAgg can not test for Far-Future headers internally and you will need to use an external tool in order to do so. Warnings given or not given about AdvAgg Expires, Cache-Control, and If-Modified-Since might be incorrect. In the <a href="@readme">readme</a>, under Troubleshooting try the Far-Future recommendations.', array(
                            '@readme' => url(drupal_get_path('module', 'advagg') . '/README.txt'),
                        )),
                    );
                }
            }
            if ($type === 'css' && (empty($request->headers['content-type']) || strpos($request->headers['content-type'], 'text/' . $content_type) === FALSE)) {
                // Recommend servers configuration be adjusted.
                $requirements['advagg_' . $type . '_type' . $key] = array(
                    'title' => $t('Adv CSS/JS Agg - Content-Type'),
                    'severity' => REQUIREMENT_WARNING,
                    'value' => $t('The wrong Content-Type is being sent by your web server.'),
                    'description' => $t('The web servers configuration will need to be adjusted. Was looking for <code>@typematch</code>, actually got <code>@received</code>.', array(
                        '@typematch' => 'text/' . $content_type,
                        '@received' => isset($request->headers['content-type']) ? $request->headers['content-type'] : 'NULL',
                    )),
                );
            }
            if ($type === 'js' && (empty($request->headers['content-type']) || strpos($request->headers['content-type'], 'application/' . $content_type) === FALSE && strpos($request->headers['content-type'], 'application/x-' . $content_type) === FALSE)) {
                // Recommend servers configuration be adjusted.
                $requirements['advagg_' . $type . '_type' . $key] = array(
                    'title' => $t('Adv CSS/JS Agg - Content-Type'),
                    'severity' => REQUIREMENT_WARNING,
                    'value' => $t('The wrong Content-Type is being sent by your web server.'),
                    'description' => $t('The web servers configuration will need to be adjusted. Was looking for <code>@typematch</code>, actually got <code>@received</code>. You might need to apply the drupal core patch located here <a href="@url">@url</a>.', array(
                        '@url' => 'https://drupal.org/node/2193333#comment-8469991',
                        '@typematch' => 'application/' . $content_type,
                        '@received' => isset($request->headers['content-type']) ? $request->headers['content-type'] : 'NULL',
                    )),
                );
            }
            // Test far future headers.
            $apache_module_missing = FALSE;
            if (!variable_get('advagg_skip_far_future_check', ADVAGG_SKIP_FAR_FUTURE_CHECK) && empty($_SERVER['PANTHEON_ENVIRONMENT']) && empty($_SERVER['PANTHEON_SITE_NAME'])) {
                // Make sure the expires header is at least set to 1 month
                // (2628000 seconds) in the future.
                if (!empty($request->headers['expires']) && strtotime($request->headers['expires']) < time() + 2628000) {
                    // Recommend servers configuration be adjusted.
                    if ($is_apache && $mod_headers === FALSE) {
                        $apache_module_missing = TRUE;
                    }
                    else {
                        $requirements['advagg_' . $type . '_expires' . $key] = array(
                            'title' => $t('Adv CSS/JS Agg - Expires'),
                            'severity' => REQUIREMENT_WARNING,
                            'value' => $t('The expires header being sent by your web server is not at least 1 month in the future.'),
                            'description' => $t('The web servers configuration should be adjusted only for AdvAgg files. Was looking for a second counter over 2,628,000 (1 month), actually got <code>@received</code> (@expires). You can turn this warning off if you can not adjust this value (Pantheon) by adding this to your settings.php file: <code>@skipcode</code>', array(
                                '@received' => isset($request->headers['expires']) ? number_format(strtotime($request->headers['expires']) - REQUEST_TIME) : 'NULL',
                                '@expires' => isset($request->headers['expires']) ? $request->headers['expires'] : 'NULL',
                                '@skipcode' => '$conf[\'advagg_skip_far_future_check\'] = TRUE;',
                            )),
                        );
                    }
                }
                // Make sure the cache-control header max age value is at least set to
                // 1 month (2628000 seconds) in the future.
                $matches = array();
                if (empty($request->headers['cache-control']) || !preg_match('/\\s*max-age\\s*=\\s*(\\d+)\\s*/is', $request->headers['cache-control'], $matches) || $matches[1] < 2628000) {
                    // Recommend servers configuration be adjusted.
                    if ($is_apache && $mod_headers === FALSE) {
                        $apache_module_missing = TRUE;
                    }
                    else {
                        $requirements['advagg_' . $type . '_cache_control' . $key] = array(
                            'title' => $t('Adv CSS/JS Agg - Cache-Control'),
                            'severity' => REQUIREMENT_WARNING,
                            'value' => $t("The cache-control's max-age header being sent by your web server is not at least 1 month in the future."),
                            'description' => $t('The web servers configuration should be adjusted only for AdvAgg files. Was looking that the max-age second counter is over 2,628,000 (1 month), actually got <code>@received</code>. You can turn this warning off if you can not adjust this value (Pantheon) by adding this to your settings.php file: <code>@skipcode</code>', array(
                                '@received' => isset($request->headers['cache-control']) ? $request->headers['cache-control'] : 'NULL',
                                '@skipcode' => '$conf[\'advagg_skip_far_future_check\'] = TRUE;',
                            )),
                        );
                    }
                }
            }
            // Handle missing apache modules.
            if ($apache_module_missing && $is_apache && $mod_headers === FALSE) {
                $requirements['advagg_mod_headers_far_future_headers_' . $key] = array(
                    'title' => $t('Adv CSS/JS Agg - Apache'),
                    'description' => $t('The Apache module "mod_headers" is not available. Enable <a href="!link">mod_headers</a> for Apache if at all possible. This is causing far-future headers to not be sent correctly.', array(
                        '!link' => 'http://httpd.apache.org/docs/current/mod/mod_headers.html',
                    )),
                    'severity' => REQUIREMENT_WARNING,
                    'value' => $t('Apache module "mod_headers" is not installed.'),
                );
                if ($mod_expires === FALSE) {
                    $requirements['advagg_mod_headers_far_future_expires_' . $key] = array(
                        'title' => $t('Adv CSS/JS Agg - Apache'),
                        'description' => $t('The Apache module "mod_expires" is not available. Enable <a href="!link">mod_expires</a> for Apache if at all possible. This is causing far-future headers to not be sent correctly.', array(
                            '!link' => 'http://httpd.apache.org/docs/current/mod/mod_expires.html',
                        )),
                        'severity' => REQUIREMENT_WARNING,
                        'value' => $t('Apache module "mod_headers" is not installed.'),
                    );
                }
            }
            // Test 304.
            if (!variable_get('advagg_skip_304_check', ADVAGG_SKIP_304_CHECK) && empty($_SERVER['PANTHEON_ENVIRONMENT']) && empty($_SERVER['PANTHEON_SITE_NAME'])) {
                $etag_works = FALSE;
                if (isset($request->headers['etag'])) {
                    // Send an Etag header and see if the web server returns a 304.
                    $url = file_create_url($url_path . '/' . $filename);
                    $if_modified_options = $options;
                    $if_modified_options['headers'] = array(
                        'Accept-Encoding' => 'gzip, deflate, br',
                        'If-None-Match' => $request->headers['etag'],
                    );
                    if (!empty($request->options['headers']['Accept-Encoding'])) {
                        $if_modified_options['headers']['Accept-Encoding'] = $request->options['headers']['Accept-Encoding'];
                    }
                    // Set context for loopback 127.0.0.1 to ignore any SSL issues.
                    $drupal_ssl_context_options = array(
                        'verify_peer' => FALSE,
                        'verify_peer_name' => FALSE,
                        'allow_self_signed' => TRUE,
                    );
                    $if_modified_options['context'] = stream_context_create([
                        'ssl' => $drupal_ssl_context_options,
                    ]);
                    // Send request.
                    advagg_install_url_mod($url, $if_modified_options, $mod_url);
                    $request_304 = drupal_http_request($url, $if_modified_options);
                    if ($request_304->code != 304) {
                        // Recommend servers configuration be adjusted.
                        $requirements['advagg_' . $type . '_304' . $key . '_etag'] = array(
                            'title' => $t('Adv CSS/JS Agg - Etag'),
                            'severity' => REQUIREMENT_WARNING,
                            'value' => $t('The If-None-Match (Etag) header is being ignored by your web server.'),
                            'description' => $t('The web servers configuration will need to be adjusted. The server should have responded with a 304, instead a @code was returned.', array(
                                '@code' => $request_304->code,
                            )),
                        );
                    }
                    else {
                        $etag_works = TRUE;
                    }
                }
                if (isset($request->headers['last-modified'])) {
                    // Send a If-Modified-Since header and see if the web server returns a
                    // 304.
                    $url = file_create_url($url_path . '/' . $filename);
                    $if_modified_options = $options;
                    $if_modified_options['headers'] = array(
                        'Accept-Encoding' => 'gzip, deflate, br',
                        'If-Modified-Since' => $request->headers['last-modified'],
                    );
                    if (!empty($request->options['headers']['Accept-Encoding'])) {
                        $if_modified_options['headers']['Accept-Encoding'] = $request->options['headers']['Accept-Encoding'];
                    }
                    // Send request.
                    advagg_install_url_mod($url, $if_modified_options, $mod_url);
                    $request_304 = drupal_http_request($url, $if_modified_options);
                    if ($request_304->code != 304) {
                        // Recommend servers configuration be adjusted.
                        $requirements['advagg_' . $type . '_304' . $key . '_last_modified'] = array(
                            'title' => $t('Adv CSS/JS Agg - If-Modified-Since'),
                            'severity' => REQUIREMENT_WARNING,
                            'value' => $t('The If-Modified-Since (Last-Modified) header is being ignored by your web server.'),
                            'description' => $t('The web servers configuration will need to be adjusted. The server should have responded with a 304, instead a @code was returned.', array(
                                '@code' => $request_304->code,
                            )),
                        );
                    }
                    elseif (isset($requirements['advagg_' . $type . '_304' . $key . '_etag'])) {
                        // Last-Modified works, Etag is broken. 304s are working. Don't warn
                        // user.
                        unset($requirements['advagg_' . $type . '_304' . $key . '_etag']);
                    }
                }
                if ($etag_works && isset($requirements['advagg_' . $type . '_304' . $key . '_last_modified'])) {
                    // Etag works, Last-Modified is broken. 304s are working. Don't warn
                    // user.
                    unset($requirements['advagg_' . $type . '_304' . $key . '_last_modified']);
                }
                // Both the Last-Modified and Etag header are missing.
                if (empty($request->headers['last-modified']) && empty($request->headers['etag'])) {
                    // Get path to advagg .htaccess file.
                    $files = array(
                        $file_path . '/.htaccess',
                        DRUPAL_ROOT . '/.htaccess',
                    );
                    // Check for bad .htaccess files.
                    $bad_config_found = FALSE;
                    foreach ($files as $count => $file) {
                        if (!file_exists($file)) {
                            continue;
                        }
                        $contents = advagg_file_get_contents($file);
                        if (strpos($contents, 'Header unset Last-Modified') !== FALSE) {
                            $bad_config_found = TRUE;
                            $requirements['advagg_' . $type . '_last-modified_' . $key . $count] = array(
                                'title' => $t('Adv CSS/JS Agg - Last-Modified'),
                                'severity' => REQUIREMENT_WARNING,
                                'value' => $t('The Last-Modified header is not being sent out by your web server.'),
                                'description' => $t('The web servers configuration will need to be adjusted. The server should have sent out a Last-Modified header. Remove "Header unset Last-Modified" inside this file to fix the issue: @file', array(
                                    '@file' => $file,
                                )),
                            );
                        }
                    }
                    // Recommend servers configuration be adjusted.
                    if (!$bad_config_found) {
                        $requirements['advagg_' . $type . '_last-modified_' . $key] = array(
                            'title' => $t('Adv CSS/JS Agg - Last-Modified'),
                            'severity' => REQUIREMENT_WARNING,
                            'value' => $t('The Last-Modified header is not being sent out by your web server.'),
                            'description' => $t('The web servers configuration will need to be adjusted. The server should have sent out a Last-Modified header and/or an Etag header. If you can not get the Last-Modified header to work, you can try using ETags. Inside <code>@htaccess</code> right before <code>@line1</code> at the bottom of the file add in <code>@line2</code>. You will also need to remove the <code>@line3</code> line further up.', array(
                                '@htaccess' => $file_path . '/.htaccess',
                                '@line1' => '</FilesMatch>',
                                '@line2' => 'FileETag MTime Size',
                                '@line3' => 'Header unset ETag',
                            )),
                        );
                    }
                }
            }
        }
    }
}