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

64 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

  32. DaveT permalink

    Hi Andy,

    Follow the link at the beginning of this article. In a nutshell, create a new file called wp-404-handler.php and paste the code above into it. Save this file into the root of your site, then in the IIS site properties, change the 404 error code to the URL type, and point it at /wp-404-handler.php , or whatever you called it. You can then use the pretty permalinks :)

  33. Hello,

    I have used this permalink solution for some time now, and it has always worked.

    I changed my web server recently (it was a VPS using Plesk 8.4, and now it’s a bigger VPS using Plesk 9.2).

    Now, I can’t get the permalinks to work in three of the four WP installations. In the one that works, WP is installed in a virtual folder (www.luisalonsoramos.com/blog). But in the other three cases, WP is installed in the root folder (for example, blog.oscarfraustro.com).

    In both cases I have done the same things:

    * Put the wp-404-handler.php file in the root of the installation
    * Configure the 404 error page to that file, using an URL
    * Set index.php as the first default document (I have found that without this, it doesn’t work).

    The home page works fine, but while the links are generated fine, they don’t work and I get the home page (for first level URLs) or a 404 (for second-level URLs).

    Any ideas?

    Thanks,

    Luis Alonso Ramos

  34. Luis, try re-saving your permalinks in wp-admin -> settings -> permalinks.

  35. I was able to get this to work save for one big problem… My homepage won’t appear unless I include index.php.

    I’m using the most recent version of WordPress (2.9.2), and for some reason if I leave off the index.php it will show my archive page instead. The rest of the pages are working fine…

  36. Thanks for the code John.

    After installing the code, my homepage won’t appear unless I include the index.php and the rest of the pages are working fine…

    Can you please help me to fix my problem?

  37. After 3 days of headache, finally I got the solution Deleted the wp-404-handler.php and created a new one.
    Here is the new code :

    $qs = $_SERVER['QUERY_STRING'];
    $qs2= substr($qs, strpos($qs, ‘:80′)+3);
    if ($qs2==”;http://www.$$$$$$$.com/Index.php”) {$qs2=”;http://www.$$$$$$$/index.php”;}
    $_SERVER['REQUEST_URI'] = $qs2;
    $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
    include(’index.php’);

    replaced $$$$$$$ with my website name. This code did the trick !!! Thanks to orhanozcan.
    http://wordpress.org/support/topic/255815

  38. Thanks, John–and everyone–for sharing your WordPress/IIS expertise. There’s not much info out there.

    We’re using IIS 7.5, WordPressMU 2.9.2, and PHP 5.2.12 with John’s wp-404-handler.php. What’s displaying ,if we go to a page that doesn’t exist on the main blog or on a member blog, is the front page of the main blog.

    What we want to display is a custom 404 for each member blog. Each member blog theme does include a 404.php.

    If there were theme errors, I would expect to see the default 404.php’s “Error 404 – Not Found,” but all non-existent page requests display the main blog’s front page.

    Thanks in advance for any ideas you offer.

  39. Hello All,

    I applied this solution to my blog installed in my subdirectory, and it works great.

    I tried the same thing in my blog installed in the subdomain, and it doesn’t work. Any ideas as to why this is the case? I using wp 2.9.2 & IIS 6.0 Thanks!

  40. Tom permalink

    This script breaks the /index.php/feed link for RSS

    Any solutions?

  41. Tom permalink

    The exact error is:

    Warning: Cannot modify header information – headers already sent by (output started at c:\mypath\404-handler.php:7) in c:\mypath\wp-includes\feed-rss2.php on line 8

  42. Tom: Make sure there are no leading or trailing spaces at the beginning or the end of the file you create.

    Diane: WordPress Permalinks and IIS7 work together without this solution. I might suggest that you use the existing functionality if you can. You would probably need to find a plugin that can provide the custom-404 per member functionality.

    Barrett: Not sure why this might happen. You should be able to set it up on a subdomain using the same method. If not, it is probably a server configuration issue (which I wouldn’t know how to fix)

    Cricket: Good to see that works. That looks a lot like the predecessor version of this solution.

  43. Francis permalink

    Anyone has that problem? index.php works but every other pages shows empty (white)

    I use : /%postname%/

    Strangly when I type mywebsite.com/index.php//%postname%/
    it works

  44. The exact error is:

    Warning: Cannot modify header information – headers already sent by (output started at c:\mypath\404-handler.php:7) in c:\mypath\wp-includes\feed-rss2.php on line 8

  45. Again, make sure there are no leading or trailing spaces at the beginning or the end of the file you create. Put your cursor immediately after the ?> and hit delete until there are no more spaces. Do the same to remove any spaces or line breaks before the < ?php at the beginning.

  46. Hi, I have WP3.0 and this solutions works for me. except when registering a new user. Can try creating an account here: boholtech.com

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
  9. 使用wordpress的固定连接 | Just For Lee
  10. 《创想曲》电子杂志
  11. 01博客 » 修改固定链接说明
  12. WordPress 固定链接设置方式 | 诺哥
  13. 使用WordPress固定链接 « Escope
  14. 使用WordPress固定链接 – 对比----想象
  15. Why Use WordPress on Windows Server 2003?
  16. 使用固定链接 | Citi
  17. Remove Wordpress Index.php on Windows Servers | No Joke Guide
  18. windows+IIS下完美设置wordpress伪静态 - 文文策划

Leave a Reply

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

Subscribe to this comment feed via RSS