{"id":1748,"date":"2008-07-02T15:46:51","date_gmt":"2008-07-02T19:46:51","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=1748"},"modified":"2018-04-17T21:04:53","modified_gmt":"2018-04-18T01:04:53","slug":"wp-super-cache","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2008\/07\/02\/wp-super-cache\/","title":{"rendered":"WP Super Cache"},"content":{"rendered":"<p>I recently installed <a href=\"http:\/\/ocaoimh.ie\/wp-super-cache\/\">WP Super Cache<\/a> to speed up my <a href=\"http:\/\/wordpress.org\">WordPress<\/a> blogs. The regular <a href=\"http:\/\/mnm.uib.es\/gallir\/wp-cache-2\/\">WP-Cache<\/a> plug-in saves processed copies of pages, reducing the database and PHP processing overhead, but the pages are still served via PHP. WP Super Cache takes this to the next level, using <a href=\"http:\/\/httpd.apache.org\/docs\/1.3\/mod\/mod_rewrite.html\">mod_rewrite<\/a> to send requests directly to cached HTML files:\n<\/p>\n\n<pre>\nRewriteCond %{REQUEST_METHOD} !=POST\nRewriteCond %{QUERY_STRING} !.*s=.*\nRewriteCond %{QUERY_STRING} !.*attachment_id=.*\nRewriteCond %{HTTP_COOKIE} !^.*(comment_author_|wordpress|wp-postpass_).*$\nRewriteCond %{DOCUMENT_ROOT}\/blog\/wp-content\/cache\/supercache\/%{HTTP_HOST}\/blog\/$1\/index.html -f\nRewriteRule ^(.*) \/blog\/wp-content\/cache\/supercache\/%{HTTP_HOST}\/blog\/$1\/index.html [L]\n\n<\/pre>\n\n<p>If a page isn&rsquo;t yet cached, the <code>-f<\/code> test will fail, and the request will be directed to the regular WordPress PHP script (using WP-Cache). It&rsquo;s a nice system, but I hit a few snags setting it up, so I wanted to document them here.<\/p>\n\n<p>The first problem was that the super cache was not being generated. Every request was being handled by WP-Cache. It turns out that WP Super Cache (sensibly) doesn&rsquo;t add a page to the super cache unless <code>$_GET<\/code> is empty. I was using a <tt>.htaccess<\/tt> file from a much older version of WordPress, and it was packing the query string with elements of the path:<\/p>\n\n<pre>\nRewriteRule ^archives\/?$ \/blog\/index.php?pagename=archives [QSA]\nRewriteRule ^category\/(.*)\/(feed|rdf|rss|rss2|atom)\/?$ \/blog\/wp-feed.php?category_name=$1&amp;feed=$2 [QSA]\nRewriteRule ^category\/?(.*) \/blog\/index.php?category_name=$1 [QSA]\nRewriteRule ^author\/(.*)\/(feed|rdf|rss|rss2|atom)\/?$ \/blog\/wp-feed.php?author_name=$1&amp;feed=$2 [QSA]\nRewriteRule ^author\/?(.*) \/blog\/index.php?author_name=$1 [QSA]\nRewriteRule ^([0-9]{4})\/?([0-9]{1,2})?\/?([0-9]{1,2})?\/?([_0-9a-z-]+)?\/?([0-9]+)?\/?$ \/blog\/index.php?year=$1&amp;monthnum=$2&amp;day=$3&amp;name=$4&amp;page=$5 [QSA]\nRewriteRule ^([0-9]{4})\/?([0-9]{1,2})\/([0-9]{1,2})\/([_0-9a-z-]+)\/(feed|rdf|rss|rss2|atom)\/?$ \/blog\/wp-feed.php?year=$1&amp;monthnum=$2&amp;day=$3&amp;name=$4&amp;feed=$5 [QSA]\nRewriteRule ^([0-9]{4})\/?([0-9]{1,2})\/([0-9]{1,2})\/([_0-9a-z-]+)\/trackback\/?$ \/blog\/wp-trackback.php?year=$1&amp;monthnum=$2&amp;day=$3&amp;name=$4 [QSA]\nRewriteRule ^feed\/?([_0-9a-z-]+)?\/?$ \/blog\/wp-feed.php?feed=$1 [QSA]\nRewriteRule ^comments\/feed\/?([_0-9a-z-]+)?\/?$ \/blog\/wp-feed.php?feed=$1&amp;withcomments=1 [QSA]\n<\/pre>\n\n\n<p>Updating <tt>.htaccess<\/tt> file to let WordPress itself parse the path:<\/p>\n\n<pre>\n# BEGIN WordPress\n&lt;IfModule mod_rewrite.c&gt;\nRewriteEngine On\nRewriteBase \/blog\/\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . \/blog\/index.php [L]\n&lt;\/IfModule&gt;\n# END WordPress\n<\/pre>\n\n<p>fixed that problem.<\/p>\n\n<p>Now the posts were being saved to the super cache, and served from it, but the feeds were only using the regular cache. WP Super Cache is hard-coded not to cache feeds in order to avoid serving them with an incorrect content type (a.k.a. <a href=\"http:\/\/en.wikipedia.org\/wiki\/Internet_media_type\">media type<\/a> or MIME type). Feeds are <a href=\"http:\/\/www.petefreitag.com\/item\/381.cfm\">supposed<\/a> to be served as <tt>application\/rss+xml<\/tt> or <tt>application\/atom+xml<\/tt>, and <a href=\"http:\/\/feedvalidator.org\">Feed Validator<\/a> will complain if they aren&rsquo;t. But the super-cached files are all stored as <tt>index.html<\/tt> so Apache will serve them as <tt>text\/html<\/tt>. (This isn&rsquo;t a problem when using WP-Cache, because it sends the proper HTTP header depending on the type of feed being generated.)<\/p>\n\n<p>To fix this, I modified WP Super Cache to generate local <tt>.htaccess<\/tt> files inside the super cache:<\/p>\n\n<pre>\nif (is_feed()) {\n    $type = get_query_var('feed');\n    $type = str_replace('\/','',$type);\n    switch ($type) {\n        case 'atom':\n            $mediaType = \"application\/atom+xml\";\n            break;\n        case 'rdf':\n            $mediaType = \"application\/rdf+xml\";\n            break;\n        case 'rss':\n        case 'rss2':\n        default:\n            $mediaType = \"application\/rss+xml\";\n    }\n    $htaccess = @fopen (\"{$dir}.htaccess\", 'w');\n    if ($htaccess) {   \n        fputs($htaccess, \"AddType $mediaType .html\");\n        fclose($htaccess);\n    }\n}\n<\/pre>\n\n<p>For example, the file <tt>blog\/wp-content\/cache\/supercache\/mjtsai.com\/blog\/feed\/rss2\/.htaccess<\/tt> changes the content type for the <tt>index.html<\/tt> file:<\/p>\n\n<pre>\nAddType application\/rss+xml .html\n<\/pre>\n\n<p>Then I modified WP Super Cache&rsquo;s <tt>wp-cache-phase2.php<\/tt> to remove the <code>is_feed()<\/code> check from the line:<\/p>\n\n<pre>\nif( !empty( $_GET ) || is_feed() || ( $super_cache_enabled == true &amp;&amp; is_dir( substr( $supercachedir, 0, -1 ) . '.disabled' ) ) )\n<\/pre>\n\n<p>Now the feeds are super cached and served with the correct content types.<\/p>","protected":false},"excerpt":{"rendered":"<p>I recently installed WP Super Cache to speed up my WordPress blogs. The regular WP-Cache plug-in saves processed copies of pages, reducing the database and PHP processing overhead, but the pages are still served via PHP. WP Super Cache takes this to the next level, using mod_rewrite to send requests directly to cached HTML files: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2018-04-18T01:04:54Z","apple_news_api_id":"66a54b78-4d6f-4e02-bd60-06837647dee9","apple_news_api_modified_at":"2018-04-18T01:04:56Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/AZqVLeE1vTgK9YAaDdkfe6Q","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[544,1659,96,740],"class_list":["post-1748","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-apache","tag-this-blog","tag-web","tag-wordpress"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1748","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=1748"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1748\/revisions"}],"predecessor-version":[{"id":15192,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1748\/revisions\/15192"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=1748"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=1748"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=1748"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}