URL Mod-Rewrite Workaround for IIS 6.0 and Wordpress

by John on September 15th, 2009

I found that the existing solution for using pretty permalinks with Wordpress and IIS is good and lightweight, but I needed something a little more robust that fixed as many differences as possible between Apache and IIS.

This code uses the same idea as the above, but fixes more values in _SERVER and resolves a problem with _GET. It will also work with later versions (2.8+) of Wordpress.

<?php
// This is the default file for the site. Usually index.php
$default = 'index.php';

// The name of this file.
// Set this value for the URL in Custom Error Properties of your website in IIS.
// Goto: IIS Manager > Websites > [Site Name] > Properties > Custom Errors >
// 404 & 404;2 & 404;3 > URL (Requires a '/' prefix in IIS).
$thisfile = '404-handler.php';

$_SERVER['ORIG_PATH_TRANSLATED'] = str_replace($thisfile, $default, $_SERVER['ORIG_PATH_TRANSLATED']);
$_SERVER['SCRIPT_FILENAME'] = str_replace($thisfile, $default, $_SERVER['SCRIPT_FILENAME']);
$_SERVER['ORIG_PATH_INFO'] = str_replace($thisfile, $default, $_SERVER['ORIG_PATH_INFO']);
$_SERVER['SCRIPT_NAME'] = str_replace($thisfile, $default, $_SERVER['SCRIPT_NAME']);
$_SERVER['PHP_SELF'] = str_replace($thisfile, $default, $_SERVER['PHP_SELF']);
$_SERVER['PATH_INFO'] = false;

$qs =& $_SERVER['QUERY_STRING'];
$ru =& $_SERVER['REQUEST_URI'];
$pos = strrpos($qs, '://');
$pos = strpos($qs, '/', $pos + 4);
$_SERVER['URL'] = $ru = substr($qs, $pos);
$qs = trim(stristr($ru, '?'), '?');

// Required for Wordpress 2.8+
$_SERVER['HTTP_X_ORIGINAL_URL'] = $ru;

// Fix GET vars
foreach ( $_GET as $var => $val ) {
  if ( substr($var, 0, 3) == '404') {
    if ( strstr($var, '?') ) {
      $newvar = substr($var, strpos($var, '?') + 1);
      $_GET[$newvar] = $val;
    }
    unset($_GET[$var]);
  }
  break;
}
include($default);
?>

From → Development

39 Comments
  1. Nice work! I’ve added a link to the top of my original post, pointing people here for a more robust solution. Get ready for tons of “this doesn’t work, please help”-type comments :)

  2. Thanks for the code John, it works well. The only problem is that actual errors show up as a blank page. Do you think there is a way to get the script to differentiate between these and WP pages so it can re-direct to a 404 message?

  3. Dorothy, thanks for your comment. Glad to hear this works for you.

    If there’s an error in the code on a page, then it most likely happens a long time after this script runs. The ’standard’ (depending on what’s in php.ini) procedure for PHP errors is to show a blank page and record the error in the PHP logs. If you want to change that behavior, read this.

    If you’re just talking about not being able to show a 404 when a non-existent page is requested, then it is likely a problem with the theme.

    Or perhaps I am misunderstanding the question?

  4. Kerry permalink

    Hi John

    I just wanted to check…as soon as this code’s updated, does that mean I can comfortably add custom categories eg. /%category/%postname%/ or /%postname/ without any issues or having to do anything further?

    I’m just finding that the rewrite rules I’ve been looking at may not give me the flexibility I need so your solution seems like a better option!

  5. Kerry:
    Yes, that is correct.
    Remember, you also need to set the value for the 404 custom errors in the admin, to point to this script.

  6. Kerry permalink

    Thanks John.

    One last question…does this solution mean that Google will see these pages as 404’s? Sorry,maybe a stupid question, but not a techy at all and just trying to find a workable solution that’s also seo friendly!

  7. Kerry, not really. What this solution does is to send any requests that would normally end up as a 404 error to Wordpress instead of sending the actual 404 error. WordPress, in conjunction with themes & plugins determines what information should be sent in the response. If WordPress can’t figure it out, then it will send a 404 response.

    The basic, simplified process is as follows:

    1. Client requests a url from a web server eg: http://domain.com/path/filename

    2. The webserver looks for the file. If it finds it, it serves it. If it cannot find the file, it normally serves a 404 response instead.

    2a. If “Custom Error” is set, then instead of serving a 404 when the file is not found, it hands the request to the defined file (this script) for pre-processing.

    3. This script fixes some variables, then hands the request to the default file (index.php) for actual processing.

    4. The default file starts WordPress, and Wordpress checks the URL and decides what data to serve.

    5. If data is found to serve, it sends it to the client, using the information in the theme to determine how it is to be displayed.

    6. If no data can be served based on the request, it asks the theme to send a 404 response. If the theme works correctly, then the client receives a 404 page.

  8. Custom 404’s while preserving the ability to have permalinks are possible using this hack with a small tweak — see http://dotnetyuppie.com/2009/09/21/permalinks-and-mod_rewrite-headaches-in-wordpress-with-iis/

  9. Just an fyi that you also need the tags around the page otherwise it will just get dumped to the screen verbatim.
    I’m also wondering if the blank pages are obtained due to the ORIG_PATH_TRANSLATED variable. This is depreciated and when I run the script on my server (for some reason) I’m getting PHP Notice: Undefined index: ORIG_PATH_TRANSLATED in wp-404-handler.php on line 11
    Now according to my reading I have cgi.fix_pathinfo=0 and I also have display_errors = off so in theory I shouldn’t get any error messages, but I’m wondering if this is why some users get blank pages – the system is erroring on line 11 but the error is also being suppressed?

  10. James Rowland permalink

    Thanks for the great code John. Only problem I seem to be having is that I can’t view comments or individual posts – The url changes correctly but nothing else seems to be changing. Only the default blog page is displayed:

    http://zoost.ie/blog/

    Any help would be great thanks!

  11. James Rowland permalink

    Disregard above comment. I hadn’t deleted the .htaccess file. All working fine now.

  12. Works great. Thanks. Migrating from Apache to IIS and I thought that this was a show stopper. Thanks for this.

  13. Hi,

    First off, thank you for creating a fix to allow Pretty Permalinks (not just Almost) on IIS.

    Bug symptom
    ———
    I don’t get a blank page but rather, the standard browser Error 404 (IIS still sends the header) when a non-existent page is requested.

    Conditions
    ——-
    Site is hosted at ReadyHosting.com on a shared Windows 2003 Enterprise Server running PHP v.5.2.0 and MySQL v.4.1.22 and a WordPress 2.8.5 that is configured to the default “Kubrick” theme which contains a 404.php template.

    Because of other plugins I was debugging, tech support there seems to have installed and enabled ISAPI_Rewrite but I’m not convinced it is even needed to get the other plugins working because I still had some code to redo on them.

    Upon request, I can send you the httpd.ini and php.ini files, You can also access http://lsgh76.org/phpinfo.php, which is up temporarily.

    I used the name 404.php for the file but buried it in the /wordpress directory which I disallow access to robots and I have configured the custom 404 page at the web host to point to it. As I said, the script works fine except for the error it still delivers for non-exisitent files or directories.

    Suspicions
    ———
    Should there be a couple of lines at the top of the code to check for this and break before processing the URL?

    BTW, I tried the alternative fix by dotnetyuppie.com (http://dotnetyuppie.com/2009/09/21/permalinks-and-mod_rewrite-headaches-in-wordpress-with-iis/). His fix sends a blank page to my browser – not even the 404 Template of WordPress. Might a combination of the two scripts work?

    Thanks in advance for any help you might extend.

    Regards,
    Pepper Nakpil

  14. Matt permalink

    Thanks for the code! Once it’s put in, however, existing links going to http://foo.bar/index.php/* links put up a 404. Is there any way to have them gracefully redirect to http://foo.bar/* ?

  15. Pepper, I would recommend that you:

    1. Ensure 100% that the ISAPI rewrite that the host installed is not active.
    2. Ensure you have installed the custom-404 script correctly and that it is publicly accessible.
    3. Have no spaces outside the `< ?php ... ?>` tags in the script file.

    Matt: That seems like strange behavior.. It doesn’t do that on this site: Test: Click here. Perhaps it is a configuration of your webserver? You may want to try googling PATH_INFO on IIS

  16. Yay! This worked for me on Enom.com iis hosting — and they’re notoriously tricky. Thank you very very much!

  17. Sokratesagogo permalink

    Thanks for the code – brilliant!

    Just someone else out there is daft enough to try and install a second WP installation within a subfolder of the first, make sure that you change the 404 entry in the IIS subfolder to point at /subfolder/404-handler.php

  18. Sokratesagogo permalink

    On pondering this a bit more, what does using the IIS handling do for your Google ranking? Does Google see the 404 first before the page is redirected?

  19. Thanks John this is a lifesaver. I was struggling previously as the other IIS ISAPI Dlls that you can install were not working and this works a treat.

    MUCH appreciated.

    Was wondering if you could help with a problem I’ve got that this 404 workaround introduced with a pluggin called Quizzin. It shows a set of quiz questions and you click on a ‘Submit’ button. Your score is displayed with the correct answers. Without the 404 handler it works OK but with it it just reloads the questions. It seems it is the same .php file used to display the questions and answers – any idea way it may not load properly?

  20. Dave permalink

    Will this also work with IIS7? Thanks!

  21. Dave permalink

    Yes, works on GoDaddy WIMP with their new grid hosting with IIS7 where they no longer install the Microsoft URL Rewrite module.

  22. Hi John,

    just wanted to thank yo for the code for the 404 file above, this worked a treat for me! :-) Been looking for fix for this for ages on IIS6 and nothing worked until i tried this.

    Cheers again,

    Gerry

  23. Sokratesagogo: Search Engines won’t see the 404. I can’t think of any reason why this configuration would have a negative impact on SEO.

    Alec:

    Unfortunately, the issue you are describing is a ‘feature’ with IIS 6. There is a hotfix for IIS 7.

    In summary, the POST data is lost when IIS forwards the request to the custom error page. The workaround is to tell your plugin to post to the ‘index.php’ version of the page, instead of the rewritten page.

    For example: on the contact page on this site, I tell CForms to post to “/index.php?page_id=34″ instead of “/contact/”. Some plugins let you do this through a configuration setting. Others you may need to hack.

    This is definitely a limitation of IIS 6. Perhaps it’s time to switch to Apache? ;)

  24. I’m a .NET not a php programmer but shouldn’t it be pos+3 not pos+4? Can you please explain what the various parts of your code fix/address? I do have it working but would like to understand it better. Thanks so much, Dave

  25. Never mind. That was my stupid question of the week. +4 is actually more efficient and allows for a legal url even if only 1 char long…would still love to know all the other stuff in your code does. Thanks, Dave

  26. Hi John,
    Could you give me an idiots guide, I have the code, and saved as 404-handler.php

    I have uploaded this via ftp to the blog root, what else do I need to do?

    The problem I have over on http://www.taggeriffic.com is that in FireFox all is fine and works out the box, with IE any $_GET calls end with a 404 page.

    This is not standard WP but WPMU with BuddyPress and the 404 pages are driving me mad.

    This came back from my ISP’s forum:

    The redirecting pages are being served with a 404 Page not found header, which IE must be reading and then ignoring the subsequent refresh header.

    As an example here is the sort of header the app is serving, you may wish to post it back in the BuddyPress forum:

    Code:
    HTTP/1.1 404 Not Found
    Cache-Control: no-cache, must-revalidate, max-age=0
    Pragma: no-cache
    Content-Length: 0
    Content-Type: text/html; charset=UTF-8
    Expires: Wed, 11 Jan 1984 05:00:00 GMT
    Last-Modified: Mon, 21 Dec 2009 15:19:00 GMT
    Server: Microsoft-IIS/6.0
    X-Server: BERYLLIUM
    X-Powered-By: ASP.NET
    X-Powered-By: PHP/5.2.11
    Set-Cookie: PHPSESSID=123f18412c96f45681b036e6fea8c123; path=/
    X-Pingback: http://taggeriffic.com/xmlrpc.php
    Refresh: 0;url=http://taggeriffic.com/members/exampleuser/
    Date: Mon, 21 Dec 2009 15:19:00 GMT
    Connection: close

    This is way above my skills would you comment please?

    David

  27. You can see it if you visit http://www.taggeriffic.com, in the top right there is an option Visit > Random Member, Forum or Blog, these work fine in FireFox but IE gives the 404 page, all the latest installs.

    Thanks

    David

  28. Thanks so much for this, after much distress this worked like a charm!

  29. techtech permalink

    Hello,

    I follow ur instruction, but it suppose to show http://www.abc.comy/category/marketing/page/2 but it end up showing http://www.abc.comy/marketing/page/2 without the category which is wrong url. Please advise. My setting in WP permalink as below:

    Custom Structure : /%category%/%postname%/

    Category base: category

  30. Hi John,

    Thanks for your reply and sorry it’s taken me time to respond – was working on another workaround, hosting the quix plugin on a linux/apache version of wordpress and using iframe to reference, dirty but it works.

    Should look at moving to Apache – but times limited.

    Alec

  31. Hi John,

    Im a wordpress 2.9 user and relatively new to code. I am just in the process of setting up pretty permalinks and am having the 404 troubles. Just a quick question:

    Where do i actually embed this code to make things work.

    Hope this makes sense

Trackbacks & Pingbacks

  1. Pretty Wordpress Permalinks on IIS » tech.einaregilsson.com
  2. Permalinks and mod_rewrite Headaches in Wordpress with IIS | Dot Net Yuppie
  3. Brian On Software » Blog Archive » Migrating a Wordpress site from BlueHost to WebHost4Life
  4. sawathee » Blog Archive » Using Permalinks
  5. Permalinks on a GoDaddy WIMP setup « 49thLatitude
  6. windows+IIS下完美设置wordpress伪静态 | 陈方毅的灵感日志
  7. Để không có ký tự tiếng việt ở url wordpress (Nicer permalinks for Vietnamese) | Script Online Collection - Free nulled script - Clone sites
  8. WordPress Pretty Permalinks on IIS | danlefeb.com

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS