Forum Moderators: phranque
When I install the wordpress permalinks htaccess in my root, stuff in my cgi-bin directory gets an access denied error message:
here's my wordpress htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
And here's what's in the <directory> block for my cgi-bin in my httpd conf file:
AllowOverride All
Options None ExecCGI
DirectoryIndex index.html
AddHandler cgi-script .cgi .pl
Order allow,deny
Allow from all
Any thoughts on what's causing my cgi-bin programs to get access denied? Or how to opt out my cgi-bin directory from the root .htaccess directives?
RewriteCond $1 !^(cgi-bin¦excludedDir2¦file\.html)
This allows access to /cgi-bin, /excludedDir1, /dir2, and /file.html outside of Wordpress. The problem you're running into exists because the default Wordpress .htaccess rewrites any folder or file in its directory or any subdirectory to be "routed" by its own systems in index.php--which, for security reasons, don't allow just any URL through; only ones that it expects. The line I gave above tells Apache to not direct URLs starting with the indicated folder and file names to Wordpress's handler--this should allow the browser to reach them normally.
Speed up your WP mod_rewrite code by a factor of more than two:
# BEGIN WordPress
#
RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point,
# you may delete or comment-out the following RewriteBase directive
# RewriteBase /
#
# if this request is for "/" or has already been rewritten to WP
RewriteCond $1 ^(index\.php)?$ [OR]
# or if request is for image, css, or js file
RewriteCond $1 \.(gif¦jpg¦ico¦css¦js)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
#
# END wordpress
This is a total replacement for the code supplied with WP as bounded by the "Begin WP" and "End WP" comments, and fixes several performance-affecting problems. Notably, the unnecessary and potentially-problematic <IfModule> container is completely removed, and code is added and re-structured to both prevent completely-unnecessary file- and directory- exists checks and to reduce the number of necessary -exists checks to one-half the original count (due to the way mod_rewrite behaves recursively in .htaccess context).
Joomla .htaccess code can benefit from an almost-identical modification.
Jim
In addition, there's the maintenance problem of keeping up with a long and difficult-to-read list.
So this shouldn't be an exhaustive list, but rather a list of the "high runners" as determined by number of accesses per unit time on any given site (check your stats). In that regard, every site will be different, and every site is likely to benefit from a slightly-different tweaking or tuning of this code snippet.
Jim
[edit] Clarified wording in first pp by adding words in brackets. [/edit]
[edited by: jdMorgan at 7:14 pm (utc) on Jan. 6, 2010]
I didn't want to bring it up in the other thread, because I didn't want to derail the discussion, but I was wondering the magnitude of the savings. A priori, I would guess this would be minor compare to, say, one plugin with a slow query.
Obviously, the advantage here is that it will have the same results in all cases and you don't need to do benchmarking and profiling to find this slowdown. I'm guessing this is a single-digit millisecond thing, whereas a slow query can be a slowdown of a full second or more in the worst cases as wheel recently discovered with his WP issues.
Any thoughts?
An important key to getting and staying rich is to not waste money. Similarly, an important key to avoid slowing down your site or being forced into an early server upgrade is to not waste CPU time. The out-of-the-box WP and Joomla rewrite code does four file- and directory-exists checks for each and every request to the server. IMHO, that's a waste of CPU time.
I can't fix all of the badly-written WP plug-ins, but I can certainly try to correct the obviously-wasteful shortcomings in this code snippet. Just because I cannot do the former doesn't mean that I shouldn't bother with the latter.
The best time to correct performance problems is at the outset. You won't have to fix problems tomorrow that you've already corrected today. I'm old-school -- from the days when 64kB was a *lot* of memory and CPU clock rates were measured in kilohertz. So I believe that it's easier to write tight fast code from the outset than to have to go find problems later and fix them.
Note that I did not write the front-page "news" title about speeding up (all of) WordPress by a factor of two and I make no such claim. I posted above that this mod will speed up the WP .htaccess code by a factor of two (or better), which it does by avoiding the second-pass exists checks on index.php itself, and avoiding exists-checks on resources such as image files which obviously don't need to be handled by WP. Since image requests comprise over 50% of the requests on a typical site, I'm quite comfortable with that claim as I wrote it.
I'd be happy to get some feedback here on any observable (or at least measurable) performance changes -- especially from busy sites with few plug-ins that are already experiencing slow page loads on heavily-shared virtual hosting where the server is "challenged" and such tweaks will make the most difference.
Jim
Note that I did not write the front-page "news" title about speeding up (all of) WordPress by a factor of two and I make no such claim.
Yes, I understood that and was reading your comments as intended. And I think these effects are more substantial than I expected. I always think of basic filesystem ops as fast compared to processing a lot of scripts or doing complex queries.
I'll have a less cavalier attitude about that now.
I use wordpress, but I have the mod_rewrite code in httpd.conf.
I wrote a script that loops over 1 dynamic (wordpress-served) document and 5 static documents, and retrieves all of them many times, outputting the elapsed time for the whole set.
I can detect no speedup at all due to the new mod_rewrite code. I've eliminated network latency as a factor, and I think I've controlled for Apache process forking too.
In my tests, requests for wordpress-handled documents are significantly slower (more than 10x slower) than requests for static documents. This is true with either the new mod_rewrite code or the old.
I'm happy to do more testing, if anyone has suggestions to try. Below is the domain-sanitized version of the code I'm using:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^example\.org$ [NC]
RewriteRule ^(.*)$ http://example.org/$1 [R=301,L]
# Unless you have set a different RewriteBase preceding this point,
# you may delete or comment-out the following RewriteBase directive
# RewriteBase /
#
# if this request is for "/" or has already been rewritten to WP
RewriteCond $1 ^(index\.php)?$ [OR]
# or if request is for image, css, or js file
RewriteCond $1 \.(gif¦jpg¦ico¦css¦js¦mp3¦wav¦pdf)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
(My original code uses solid pipe characters to delineate the file extensions in the RewriteCond rule)
# if this request is for any of these filetypes
RewriteCond $1 \.gif$ [NC,OR]
RewriteCond $1 \.jpg$ [NC,OR]
RewriteCond $1 \.ico$ [NC,OR]
RewriteCond $1 \.css$ [NC,OR]
RewriteCond $1 \.js$ [NC,OR]
RewriteCond $1 \.mp3$ [NC,OR]
RewriteCond $1 \.wav$ [NC,OR]
RewriteCond $1 \.pdf$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
# if this request is for any of theses filetypes
RewriteCond $1 \.gif$ [NC,OR]
RewriteCond $1 \.jpg$ [NC,OR]
RewriteCond $1 \.ico$ [NC,OR]
RewriteCond $1 \.css$ [NC,OR]
RewriteCond $1 \.js$ [NC,OR]
RewriteCond $1 \.mp3$ [NC,OR]
RewriteCond $1 \.wav$ [NC,OR]
RewriteCond $1 \.pdf$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^/(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule ^/. /index.php [L]
[edited by: jdMorgan at 11:32 am (utc) on Aug 27, 2010]
Jim
RewriteCond $1 \.(gif¦jpg¦ico¦css¦js)$ [NC,OR] you will need to set up a non-WordPress 404 page.
I've opened a ticket specifically about the internal re-re-writing of index.php at [core.trac.wordpress.org...]
[added] The reason for this is that the browser will show a broken image, broken styling, or some other problem; It won't actually render the 404 'page' that it got with the object fetch error. [/added]
Jim