Skip to content

Commit

Permalink
Better content-type handling
Browse files Browse the repository at this point in the history
Content-Type text/html is not always the ideal way of serving cached output.
We should respect WordPress' default behavior and content should be the same type.

fixes #33
  • Loading branch information
mustafauysal committed Dec 8, 2017
1 parent 9351fe2 commit b74009e
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 10 deletions.
79 changes: 69 additions & 10 deletions includes/dropins/page-cache.php
Expand Up @@ -224,7 +224,32 @@ function powered_cache_page_buffer( $buffer, $flags ) {
}
}

$index_name = powered_cache_index_file();


$meta_file_name = 'meta.php';
$meta_file = '<?php exit; ?>' . PHP_EOL;

$meta_params = array(); // holds to metadata for cached file

$response_headers = powered_cache_get_response_headers();

foreach ( (array) $response_headers as $key => $value ) {
$meta_params['headers'][ $key ] = "$key: $value";
}

$meta_params = apply_filters( 'powered_cache_page_cache_meta_params', $meta_params, $response_headers );
$meta_file_contents = $meta_file . serialize( $meta_params );

$meta_file_contents = apply_filters( 'powered_cache_page_cache_meta_info', $meta_file_contents );

$filesystem->put_contents( $path . '/' . $meta_file_name, $meta_file_contents, FS_CHMOD_FILE );
$filesystem->touch( $path . '/' . $meta_file_name, $modified_time );

if ( isset( $meta_params['headers']['Content-Type'] ) ) {
$index_name = powered_cache_index_file( $meta_params['headers']['Content-Type'] );
} else {
$index_name = powered_cache_index_file();
}

if ( $GLOBALS['powered_cache_options']['gzip_compression'] && function_exists( 'gzencode' ) ) {
$filesystem->put_contents( $path . '/' . $index_name, gzencode( $buffer, 3 ), FS_CHMOD_FILE );
Expand All @@ -234,12 +259,12 @@ function powered_cache_page_buffer( $buffer, $flags ) {
$filesystem->touch( $path . '/' . $index_name, $modified_time );
}

do_action( 'powered_cache_page_cached', $buffer );

header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary

header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );

do_action( 'powered_cache_page_cached', $buffer );

if ( function_exists( 'ob_gzhandler' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
return ob_gzhandler( $buffer, $flags );
} else {
Expand All @@ -255,11 +280,25 @@ function powered_cache_page_buffer( $buffer, $flags ) {
*/
function powered_cache_serve_cache() {

$file_name = powered_cache_index_file();

$path = rtrim( $GLOBALS['powered_cache_options']['cache_location'], '/' ) . '/powered-cache/' . rtrim( powered_cache_get_url_path(), '/' ) . '/' . $file_name;
$path = rtrim( $GLOBALS['powered_cache_options']['cache_location'], '/' ) . '/powered-cache/' . rtrim( powered_cache_get_url_path(), '/' ) . '/';

$meta_file = $path.'/meta.php';


if ( @file_exists( $meta_file ) ) {
$meta_contents = trim( file_get_contents( $meta_file ) );
$meta_contents = str_replace( '<?php exit; ?>', '', $meta_contents );
$meta_params = unserialize( trim( $meta_contents ) );
$header_params = $meta_params['headers'];
}

$content_type = @$header_params['Content-Type'];

$file_name = powered_cache_index_file( $content_type );
$file_path = $path.$file_name;

$modified_time = (int) @filemtime( $path );
$modified_time = (int) @filemtime( $file_path );

header( 'Cache-Control: no-cache' ); // Check back in an hour

Expand All @@ -268,15 +307,21 @@ function powered_cache_serve_cache() {
exit;
}

if ( @file_exists( $path ) && @is_readable( $path ) ) {
if ( @file_exists( $file_path ) && @is_readable( $file_path ) ) {

header( 'X-Powered-Cache: php' );
if ( ! empty( $header_params ) ) {
foreach ( $header_params as $key => $response_header ) {
header( $response_header );
}
}

header( 'X-Powered-Cache: PHP' );

if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
header( 'Content-Encoding: gzip' );
}

@readfile( $path );
@readfile( $file_path );

exit;
}
Expand Down Expand Up @@ -312,10 +357,14 @@ function powered_cache_get_user_cookie() {

/**
* Determines cache file names
*
* @param string $content_type
*
* @since 1.0
* @since 1.2 `$content_type`
* @return string
*/
function powered_cache_index_file() {
function powered_cache_index_file( $content_type = 'text/html' ) {
$file_name = 'index';

if ( powered_cache_is_ssl() ) {
Expand Down Expand Up @@ -355,6 +404,16 @@ function powered_cache_index_file() {
$file_name .= '_' . sha1( $_SERVER['QUERY_STRING'] );
}

/**
* Content-Type is not always text/html (like feed, wp-json etc..)
* We should respect proper format!
* Alternatively, we can add multiple level lookup for apache/nginx config
* but that makes things much more complicated.
*/
if ( false === strpos( $content_type, 'text/html' ) ) {
$file_name .= '-' . mb_substr( sha1( $content_type ), 0, 6 );
}

$file_name .= '.html';

if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
Expand Down
87 changes: 87 additions & 0 deletions includes/functions.php
Expand Up @@ -596,6 +596,93 @@ function powered_cache_fragment( $key, $ttl, $function ) {
}


/**
* Fetches known headers, ported from WP Super Cache but not using apache_response_headers
*
* @since 1.2
* @return array|false
*/
function powered_cache_get_response_headers() {
static $known_headers = array(
'Access-Control-Allow-Origin',
'Accept-Ranges',
'Age',
'Allow',
'Cache-Control',
'Connection',
'Content-Encoding',
'Content-Language',
'Content-Length',
'Content-Location',
'Content-MD5',
'Content-Disposition',
'Content-Range',
'Content-Type',
'Date',
'ETag',
'Expires',
'Last-Modified',
'Link',
'Location',
'P3P',
'Pragma',
'Proxy-Authenticate',
"Referrer-Policy",
'Refresh',
'Retry-After',
'Server',
'Status',
'Strict-Transport-Security',
'Trailer',
'Transfer-Encoding',
'Upgrade',
'Vary',
'Via',
'Warning',
'WWW-Authenticate',
'X-Frame-Options',
'Public-Key-Pins',
'X-XSS-Protection',
'Content-Security-Policy',
"X-Pingback",
'X-Content-Security-Policy',
'X-WebKit-CSP',
'X-Content-Type-Options',
'X-Powered-By',
'X-UA-Compatible',
'X-Robots-Tag',
);

$known_headers = apply_filters( 'powered_cache_known_headers', $known_headers );

if ( ! isset( $known_headers['age'] ) ) {
$known_headers = array_map( 'strtolower', $known_headers );
}

$headers = array();

if ( function_exists( 'headers_list' ) ) {
$headers = array();
foreach ( headers_list() as $hdr ) {
$header_parts = explode( ':', $hdr, 2 );
$header_name = isset( $header_parts[0] ) ? trim( $header_parts[0] ) : '';
$header_value = isset( $header_parts[1] ) ? trim( $header_parts[1] ) : '';

$headers[ $header_name ] = $header_value;
}
}


foreach ( $headers as $key => $value ) {
if ( ! in_array( strtolower( $key ), $known_headers ) ) {
unset( $headers[ $key ] );
}
}

return $headers;
}


if ( ! function_exists( 'boolval' ) ) {
/**
* For compatible reason.
Expand Down

0 comments on commit b74009e

Please sign in to comment.