IIS + PHP Pretty URL (key,value) removes double slashes - iis

There has been a migration from a apache server to IIS, the base transfer was pretty easy and it is running, but I've got a rather annoying issue that I would like to solve.
The issue: They are using zii 'cgridview' to show their tables; while it's not a pretty solution (might be the implementation), it worked fine for Apache.
The pagination itself works fine but when they are filtering it; it will do a 'GET' to get all the information, this sort of works for the first time but when we paginate to another page it suddenly go haywire (because it's a GET).
The issue here is it will do a request with all the filters, so it's like:
https://example.com/controller/action/filter1/value/filter2//filter3//filter4/hallo
This is normally the correct format how it should work (with apache rewrite at least), however IIS does not seem to like this, in my opinion why?
If you like closer we got a filter1 and the next parameter is a value; filter2 does not have a value so it's empty and there now two 'slashes' (between those slashes is nothing; so it's empty) but as far I can imagine IIS is trimming those slashes away so it's a single slash.
Filter for filter1 works as expected; but filter2 will have filter3 as value; which is not correct.
Does anyone have an idea what can cause this issue?
The rewrite is like this:
<rule name="yii_rewrite" stopProcessing="true">
<match url="." ignoreCase="false" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" appendQueryString="true" />
</rule>
Thank you for your time, appreciate it!

At present, these double slashes will be processed by the modern IIS/Apache webserver. Only some old browsers will convert the double slashes to another meaning. thereby, we could add URL Rewrite rules in IIS/Apache server to remove the extra slash, just like below.
mod_rewrite in Apache.
# remove multiple slashes anywhere in url
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]
Equally, in the IIS URL Rewrite module.
<rewrite>
<rules>
<rule name="Imported Rule" stopProcessing="true">
<match url="." ignoreCase="false" />
<conditions>
<!--# remove multiple slashes anywhere in url -->
<add input="{URL}" pattern="^(.*)//(.*)$" ignoreCase="false" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{C:1}/{C:2}" />
</rule>
</rules>
</rewrite>
Please refer to the below link for more details.
https://webmasters.stackexchange.com/questions/8354/what-does-the-double-slash-mean-in-urls/8381#8381

I suggest to disable this behavior completely by settings CUrlManager::$appendParams to false. As a result you should get URLs like https://example.com/controller/action?filter1=value&filter2=&filter3=&filter4=hallo, which should be less confusing not create any problems.

As far I am aware the problem is caused because the 'REQUEST_URI' is encoded by default, double slashes are turned to single slashes. In order to resolve this issue; we can replace the REQUEST_URI with UNENCODED_URL; that way the double slashes remains.
This works but IIS must have had their reasons for that; it's better to fix it in code and not putting a band aid on it. If this can cause issues; I would love to hear about it - preferably I would like to resolve this cleanly even though this is old code that will stop at the end of the year.
<serverVariables>
<set name="REQUEST_URI" value="{UNENCODED_URL}" />
</serverVariables>

Related

IIS url redirect rule in web.config

I want to write a rule for a redirect in my web.config.
I want to redirect urls like...
http://www.example.net/profile/username
to...
http://www.example.net/#/profile/username
I have added the below run but it doesn't seem to work. What is the best way to do this?
<rule name="Redirect to hashed profile" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}{REQUEST_URI}" pattern="on" ignoreCase="true" pattern="^.net/profile/*"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/#/{REQUEST_URI}" redirectType="Permanent" appendQueryString="true" />
</rule>
Here's what's going on and how you fix it.
pattern="^.net/profile/*"
The ^ anchors the text to the beginning of your HTTP_HOST which is www.example.com So ^.net means your URL must start with any 1 character . and then the word net. I'm going to assume you meant you wanted to match the literal ., in order to do that you have to escape it as \.
You also have to escape the / to \/ and also * at the end of a slash just means match unlimited slashes, but you want it to match any character after the slash unlimited times, so it's .*
So let's rewrite that pattern as we can't use the ^ because your website don't start with .net
pattern="\.net\/profile\/.*"
That will give you this..
<add input="{HTTP_HOST}{REQUEST_URI}" pattern="on" ignoreCase="true" pattern="\.net\/profile\/.*">
But do you really need the {HTTP_HOST}? It really depends if this is a global rule, if it's not a global rule, and it's at the application level. Then you don't need it.
Now you can add back in the ^ to anchor the word profile to the first part of the REQUEST_URI like this.
<add input="{REQUEST_URI}" pattern="on" ignoreCase="true" pattern="^profile\/.*">

IIS Rewrite Rule - how to manipulate {HTTP_HOST} string

I've just started using iis rewrite rules for the first time and I'm struggling with what I imagine is an easy rule.
Basically, I wish to use this rule
<rule name="redirect">
<match url="^(one$|two$|three$)" />
<action type="Redirect" url="{HTTP_HOST}{REQUEST_URI}" />
</rule>
But have the redirect {HTTP_HOST} string minus the extension [.co.uk / .com etc.].
e.g.
bigsite.co.uk/one
would redirect to:
bigsite.co.uk/bigsite/one
How does one go about this - for I can only find Tolower / UrlEncode / UrlDecode string manipulators?
[Ultimately, I would also like to then use a rewrite rule to hide the fact that the redirect has occurred, i.e. the address would remain as bigsite.co.uk/one after the redirect.]
Well I eventually came up with this (hope it may help someone):
<rule name="redirect">
<match url="^(one$|two$|three$)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www.)?(.*).co.uk" />
</conditions>
<action type="Redirect" url="{C:2}{REQUEST_URI}" />
</rule>
...not sure if there is a better way, but it works perfectly for me - thanks all, PP

IIS Trailing Slash rule does not remove trailing slash from root of domain

I'm using the "standard" remove trailing slash rule
<rule name="SEO - Remove trailing slash" stopProcessing="false">
<match url="(.*)/$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}" />
</rule>
this works fine for all URL's on the site except the root www.mysite.com which appends at least one trailing slash, and URLs such as www.mysite.com//// are also not dealt with (and making their way into search engines). I've disabled all other rules, and this still occurs. How do I tidy up the root of the site?
Incidentally the TEST button in the IIS management console indicates that the rule should work. It simply doesn't.
EDIT:
Further research shows an article from Google on this http://googlewebmastercentral.blogspot.co.uk/2010/04/to-slash-or-not-to-slash.html "Rest assured that for your root URL specifically, http://example.com is equivalent to http://example.com/ and can’t be redirected even if you’re Chuck Norris.", but something (probably off site) is causing /// to get into Google index so I'm looking for a way around it.
It appears that its not possible to do this, however for SEO purposes a
<link rel="canonical" href="http://www.example.com" />
seems to help resolve the ranking issue.

IIS Rewrite Map not working

I'm rebuilding a site using iis urlrewriting on both static and dynamic pages. The redirects are all working well. The rewrite module is working perfectly.
Since the site structure is changing, I need to be able to redirect "old" defunct urls to new pages. So, for example, www.sitename.com/research.asp needs to be redirected to www.sitename.com/news
I've followed the instructions to set up a rule using a rewrite map and placed the rule near the top of my webconfig file (just under the CanonicalHostNameRule). But whatever permutations I've tried in the rule, I just can get it to work. The redirects don't happen - I just get a 404 for the (non-existent) .asp page. The map just seems to be getting ignored entirely. Just to re-iterate, all my other rules are working fine.
I've tried turning off all other rules and just working with this one, but no luck. Equally, I've trawled this forum and others for suggestions (using REQUEST_URI rather than Filename, restarting IIS, recycling App. Pools, etc etc), but nothing seems to work. The "Redirect" url="{C:1}" just sends me back to the old asp page I'm trying to get redirected away from, if that makes sense. Nothing in FailedRequestTracing seems to help, either.
Am I missing something very obvious here?
The Rule:
<rule name="Redirect Rule" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="false">
<add input="{StaticRedirects:{REQUEST_FILENAME}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" redirectType="Permanent" />
</rule>
The Map:
<rewriteMaps>
<rewriteMap name="StaticRedirects">
<add key="research.asp" value="news" />
<add key="blog.asp" value="news" />
<add key="mentors.asp" value="interviews" />
<add key="regulars.asp" value="opinion" />
</rewriteMap>
</rewriteMaps>
NB - there are lots of other static redirects to add to this once it actually works, which is why I wanted to use a map.

Rewrite rules in ISS's web.config

I'm just trying to get some code running on ISS that has been running on Apache for a long time.
A particular mod_rewrite rule is proving difficult to get working.
In Apache I've used:
RewriteRule ^media/(js|css|img|font)/(.+)\.(\d+)\.(js|css|png|jpg|gif)$ /media/$1/$2.$4
[L]
To turn a URL like /media/css/style.1367406756.css into /media/css/style.css, letting me put timestamps in the files to avoid caching issues.
In my web.config file I've added:
<rule name="Cache bust assets" stopProcessing="true">
<match url="^(.*)$"/>
<conditions>
<add input="{URL}" pattern="^media/(js|css|img|font)/(.+)\.(\d+)\.(js|css|png|jpg|gif)$"/>
</conditions>
<action type="Rewrite" url="/media/{R:1}/{R:2}.{R:4}" appendQueryString="true" />
</rule>
Which, looks like it should work. (It's alongside another rule, which works fine, so it's not that the server isn't parsing it or anything).
I don't get any errors, other than visiting /media/css/style.1367406756.css gives me a 404 error.
How Can I make this work?
You use {R:N} back references in your action when you should use {C:N} since the information comes from the conditions. See Using Back-references in Rewrite Rules for more information.
You can see this error if you open the iismanager console:
To get your rule to work you have 2 solutions.
First you can change your action to (using {C:N}):
<action type="Rewrite" url="/media/{C:1}/{C:2}.{C:4}" appendQueryString="true" />
Or (and I do think it is a better solution), you can use the Import mod_rewrite Rules tool.
In the iismanager console, click on Import Rules... (on the right tab) and paste your apache rule:
This will create for you the following rule:
<rule name="Imported Rule 1" stopProcessing="true">
<match url="^media/(js|css|img|font)/(.+)\.(\d+)\.(js|css|png|jpg|gif)$" ignoreCase="false" />
<action type="Rewrite" url="/media/{R:1}/{R:2}.{R:4}" />
</rule>

Resources