So I have a custom PHP MVC framework which works perfectly fine in Apache, but having a hard time adapting it to IIS 10 FastCGI.
Here’s my structure:
/website/
- htaccess / web.config
- app folder -> Libraries (Core, Controller, Database), Controllers, Models, Views, Includes, Helpers, etc
- public folder -> css, js, index.php, htaccess / web.config
Root htaccess looks like this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
</IfModule>
Translated that into this web.config:
<rules>
<rule name="Imported Rule 1" stopProcessing="true">
<match url="^$" />
<action type="Rewrite" url="public/" />
</rule>
<rule name="Imported Rule 2" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="public/{R:1}" />
</rule>
</rules>
So, hitting “website” which routes to “website/public” works perfectly fine.
The issue is with the Public web.config. Here’s the htaccess for it:
<IfModule mod_rewrite.c>
Options -Multiviews
RewriteEngine On
RewriteBase /website/public
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
</IfModule>
Web.config translation:
<rule name="Imported Rule 1-1" stopProcessing="true">
<match url="^(.+)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<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?url={R:1}" appendQueryString="true" />
</rule>
Now I should be able to visit “website/jobs” or “website/jobs/list/0” for instance. Works perfectly fine in Apache, but I get a 404 on IIS. Haven’t been able to resolve in two days.
Appreciate any tips please! Thanks.
[EDIT] Is there any way I can trace the request? I’ve tried the Failed Requests Tracing in IIS as per this link https://wengier.com/debugging-iis-rewrite-rules/ but IIS doesn’t seem to output any 404 errors to the logs. My FRT settings seem to be missing the “RequestRouting” and “Rewrite” options as shown in the link. [EDIT2] It would seem there is a conflict between the two web.config files. If I disable the root web.config file and then type “website/public/jobs” (instead of “website/jobs” it works.
2
Answers
I fixed it. The two web.configs are conflicting with each other. So, I dropped the public/web.config completely.
My root web.config now looks like this:
Open iis select /website/public open URL Rewrite Import Rules UI, comment out the rewrite base /website/public line and import remaining rules. This will result in rewrite rules saved into the web.config file located in that directory. That will give you the same behavior as a rewrite base gives on apache.