16

In a new project we are using wp-super-cache (the client's preferred plugin) to create the static html files for custom content types. But we are trying to figure out if everything is being cached properly.

This is a 2 part question.

1) The theme we have created utilizes page templates to output json that is ingested via ajax calls. ie. if you hit the page: theurl.com/sample - you will get pure json. While there is a non-javascript version of every page and post, Ajax drives the front end of this theme. We have removed the header and footer in these files so that it is pure json, and we are trying to figure out how to determine if the json is being cached. In theory the data would be cached because it is technically a page served up by wordpress. But, how can we figure out if it is being cached?

2) We are using the json api plugin to serve up certain post data as well. http://wordpress.org/extend/plugins/json-api/ For this example, let's say we are utilizing the plugin's default method of output and hitting this page: my url.com/category/news?json=1 - Does anyone know how we can verify if this output is being cached? If it isn't being cached, what method would make this happen?

There doesn't seem to be much information about this online, so in the spirit of creating compelling and optimized wordpress sites, help a brother out

4 Answers 4

9

It did appear that the json wasn't being cached by wp-super-cache, but we decided to take a different approach. By using the transient api, we were able to do a faux-cache on all json, and drastically reduce the taxing of the database. Then on the ajax side of things, we are caching the html that is created from this semi-cached json. Things are super speedy! Here is a scaled down version of the code and concept.

    $transient_key = 'my-transient-key'; 
    $data = get_transient( $transient_key ); 

    if ( $data == '' ) { 
      $args = array(

    'post_type' => 'brand', 
    'posts_per_page' => 50

  );

  $postsArray = array();  
  // The Query
 query_posts( $args );

  // The Loop
  while ( have_posts() ) : the_post();

    $brand_id = get_the_ID();
    $slug = basename(get_permalink());
    $title = get_the_title();
    $description = get_the_content();

                $posts = array(

                   'brand_id' => $brand_id,
                   'machine_name' => $slug,
                              'postTitle' => $title,
                   'description' => $description,

                   );

    array_push($postsArray,$posts);


  endwhile;

   $data = json_encode($postsArray);


 set_transient( $transient_key, $data, 60 * 60 * 24 ); // one day
 }  // now all the brand information is cached as one table call.

echo $data;
1
  • nice, thumbs up!!!
    – Dipesh KC
    Commented Nov 21, 2012 at 11:53
6

WP Super Cache examines your WordPress site's pages for some HTML tags before it caches them.

Your pages most probably don't have </html> tag (common issue), in that case, try adding something like //</html> -- that's a workaround, and WP Super Cache should then generate cached versions of your pages.

Why does WP Super Cache do it like that? See, there's no obvious way to check if a page is only half-loaded, than to check if all the basic HTML tags exist and are closed properly.

In Donncha's (WP Super Cache's developer) own words, "It's to stop half generated pages being cached."

1
  • I wish they had the option to cache json specifically, or other data types. So many options and yet not the one we needed for this project. But, this is a cool workaround. I'll give it a try.
    – Starfs
    Commented May 9, 2012 at 4:34
4

SECURITY NOTE: This (and the other solutions) shouldn't be used unless you have a way to override the Content-Type: text/html header that WP Super Cache sends with the appropriate application/json value. Sending JSON as text/html will cause the browser to render it as HTML, which could potentially be an XSS vector.

It looks like that needs to be done at the server layer, since WPSC doesn't provide the necessary hooks.


This is how I did it. It's similar to Liang's approach, but doesn't require modifying the plugin directly, and has a more precise regex pattern.

If you're using v2 of the REST API, you should use REST_REQUEST instead of JSON_REQUEST.

It'd be good to subscribe to 22 and #79 in case something changes in WP Super Cache.

/**
 * Tell WP Super Cache to cache API endpoints
 *
 * @param string $eof_pattern
 *
 * @return string
 */
function wcorg_json_cache_requests( $eof_pattern ) {
    global $wp_super_cache_comments;

    if ( defined( 'JSON_REQUEST' ) && JSON_REQUEST ) {
        // Accept a JSON-formatted string as an end-of-file marker, so that the page will be cached
        $json_object_pattern     = '^[{].*[}]$';
        $json_collection_pattern = '^[\[].*[\]]$';

        $eof_pattern = str_replace(
            '<\?xml',
            sprintf( '<\?xml|%s|%s', $json_object_pattern, $json_collection_pattern ),
            $eof_pattern
        );

        // Don't append HTML comments to the JSON output, because that would invalidate it
        $wp_super_cache_comments = false;
    }

    return $eof_pattern;
}
add_filter( 'wp_cache_eof_tags', 'wcorg_json_cache_requests' );
2
  • Hi. I use wp_cache_eof_tags filter, but now (and only when caching is enabled) I have an error: XMLHttpRequest cannot load http://api.mywebsite.com/wp-json/wp/v2/posts. Origin http://mywebsite.com is not allowed by Access-Control-Allow-Origin. How can I fix it? Commented Mar 11, 2017 at 16:59
  • Since you've got the REST API on a separate domain, your main site is probably exporting a Access-Control-Allow-Origin header to allow the cross-origin request. I'm guessing that the cached pages aren't outputting that header.
    – Ian Dunn
    Commented Mar 12, 2017 at 17:24
0

I met this problem too. I had wrote some my code to be API. When response type was XML, cache worked. But when response type was json, it did not work.

It take my some hours to fix this bug.

This is work for me.

enter image description here

Just update your code like my changes.

It works for me now.

2
  • 6
    Please post real code and not an image of the code. Commented Sep 7, 2015 at 4:26
  • 1
    You should use the wp_cache_eof_tags filter instead of modifying the plugin directly.
    – Ian Dunn
    Commented Dec 30, 2015 at 19:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.