Cameron
Cameron

Reputation: 28803

Rewrite rules not working for CakePHP on IIS

I have been trying to get rewrite rules to work on IIS for CakePHP using the following web.config settings which is in the root folder:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
          <rules>
            <rule name="Imported Rule 1" stopProcessing="true">
              <match url="^$" ignoreCase="false" />
              <action type="Rewrite" url="app/webroot/" />
            </rule>
            <rule name="Imported Rule 2" stopProcessing="true">
              <match url="(.*)" ignoreCase="false" />
              <action type="Rewrite" url="app/webroot/{R:1}" />
            </rule>
            <rule name="Imported Rule 3" stopProcessing="true">
              <match url="^$" ignoreCase="false" />
              <action type="Rewrite" url="webroot/" />
            </rule>
            <rule name="Imported Rule 4" stopProcessing="true">
              <match url="(.*)" ignoreCase="false" />
              <action type="Rewrite" url="webroot/{R:1}" />
            </rule>
            <rule name="Imported Rule 5" stopProcessing="true">
              <match url="^(.*)$" ignoreCase="false" />
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
              </conditions>
              <action type="Rewrite" url="index.php" appendQueryString="true" />
            </rule>
          </rules>
        </rewrite>
    </system.webServer>
</configuration>

All the CSS, JS and other files work fine. As does loading in the home page, but other pages such as /pages/about just show a 404!

EDIT: Screenshot of setup in IIS:

enter image description here

What's the problem? Thanks

Upvotes: 1

Views: 5485

Answers (2)

Tarun Gupta
Tarun Gupta

Reputation: 6403

IIS7 does not natively support .htaccess files. While there are add-ons that can add this support, you can also import htaccess rules into IIS to use CakePHP’s native rewrites. To do this, follow these steps:

1.Use Microsoft’s Web Platform Installer to install the URL Rewrite Module 2.0 or download it directly (32-bit / 64-bit).

2.Create a new file in your CakePHP root folder, called web.config.

3.Using Notepad or any XML-safe editor and copy the following code into your new web.config file...

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
            <rule name="Redirect static resources" stopProcessing="true">
            <match url="^(ico|img|css|files|js)(.*)$" />
            <action type="Rewrite" url="app/webroot/{R:1}{R:2}" appendQueryString="false" />
            </rule>
            <rule name="Imported Rule 1" stopProcessing="true">
            <match url="^(.*)$" ignoreCase="false" />
            <conditions logicalGrouping="MatchAll">

                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            </conditions>
            <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true" />
            </rule>
            <rule name="Imported Rule 2" stopProcessing="true">
              <match url="^$" ignoreCase="false" />
              <action type="Rewrite" url="/" />
            </rule>
            <rule name="Imported Rule 3" stopProcessing="true">
              <match url="(.*)" ignoreCase="false" />
              <action type="Rewrite" url="/{R:1}" />
            </rule>
            <rule name="Imported Rule 4" stopProcessing="true">
              <match url="^(.*)$" ignoreCase="false" />
              <conditions logicalGrouping="MatchAll">

                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              </conditions>
              <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true" />
            </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Upvotes: 6

deizel.
deizel.

Reputation: 11212

I don't have much experience with IIS but, returning to this question, I'm noticing some glaring issues. IIS has imported all the three of CakePHP's .htaccess without any regard as to which directory they are contained in.

CakePHP comes with two additional .htaccess files so that users can easily throw an installation into Apache and, regardless of the URL they try, they should always (hopefully) be redirected to the correct .htaccess file and things should "just work" (TM):

Document root     Additional .htaccess file     Correct .htaccess file
/ --------------> /.htaccess -----------------> /app/webroot/.htaccess
/app/ ----------> /app/.htaccess -------------> /app/webroot/.htaccess
/app/webroot ---------------------------------> /app/webroot/.htaccess

The way IIS has imported these files, assuming your document root is set to /, rules 3-4 (from the second .htaccess file) are not needed. But more importantly, due to the catch-all regex (.*) in rule 2 (from the first .htaccess file), no rule beyond rule 2 will ever execute - meaning requests will never be passed to index.php.

Anyway, you are not using Apache, so you can't haphazardly throw CakePHP installations around expecting them to just work. The correct document root to use in production environments (for performance and security) on any web server (Apache, IIS, Nginx, etc) is the aptly named /app/webroot directory. This directory contains index.php, static files, and the correct .htaccess file.

After that, all you should need is rule 5 (from the correct .htaccess file). It basically reads: "match all requests and send them to index.php, unless there is a real file or directory we can serve":

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
          <rules>
            <rule name="CakePHP" stopProcessing="true">
              <match url="^(.*)$" ignoreCase="false" />
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
              </conditions>
              <action type="Rewrite" url="index.php" appendQueryString="true" />
            </rule>
          </rules>
        </rewrite>
    </system.webServer>
</configuration>

Upvotes: 3

Related Questions