Why is IIS 8.5 URL Rewrite throwing a 404 error? - url-rewriting

We have modified our file structure a bit since we've found an issue with the result in my other thread and we now we're back where we've started. I have checked out this thread but there is no answer to that question either.
We want the URL to show: https://devbox.mysite.com/kb/article/test-article-1 on the browser.
Below is my URL Rewrite:
<rule name="Article-rewrite" enabled="true">
<match url=".com/kb/article/(.*)$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="https://devbox.mysite.com/kb/article/?artID={R:1}" appendQueryString="false" />
</rule>
I have enabled Failed Request Tracing to trace rewrite rules on the IIS but when I added the rules I do not see the Rewrite as an option even though this instruction showed that it's there. This is my settings and it's not showing option. Anyway, this is just a side issue to diagnose my url rewrite issue.

Okay, so I finally figured out the answer to my question. The match URL will match the folder kb/artitcle/ and the a-ZA-Z- will only allow word and dash. In my situation, there will only be one parameter being passed so I intentionally ignoring the ampersand character because in CommonSpot CMS it adds a &cs_pgIsInLView=1 to the end of the URL which causes the rewrite rule to break. So by ignoring this ampersand, it works in my situation. The query_string pattern 1 will ignore rewrite when I tried to login to the page with the url https://devbox.mysite.com/index.cfm?login=1. I'm guess there may be other better ways than this one but for now, this will have to do.
<rule name="Article-rewrite" enabled="true">
<match url="^kb/article/([a-zA-Z\-]+)$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{QUERY_STRING}" pattern="1" negate="true" />
</conditions>
<action type="Rewrite" url="kb/article/?artID={R:1}" appendQueryString="false" />
</rule>

Related

Why Aren't My URL Rewrite Maps Changing the Browser's URL?

Environment
IIS Server 8
URL Rewrite Module 2.0 (Version 7.2.2; Microsoft)
Rewrite Maps
Static HTML Files
Background
I want to display a user-friendly URL in the Browser by using URL Rewrite Mapping.
Problem
The Browser's URL bar does not change (ie, it does not switch to the user-friendly URL).
Request
Can you please tell me how to get my URL Rewrite Mapping to actually re-write the browser's URL (to the mapped value)?
Sample Code (Web.Config)
<rule name="RewriteMapping" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{Test:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" appendQueryString="false" />
</rule>
<rewriteMaps>
<rewriteMap name="Test" defaultValue="">
<add key="foo.html" value="This-Is-A-Nice-Page-To-Remember" />
</rewriteMap>
</rewriteMaps>
To "rewrite" new canonical URLs to the underlying file
You have created a rewrite map that internally rewrites the "pretty" requested URL to the underlying URL/file that handles the request. Although you appear to have written the key/value pair the wrong way round. It should be:
<add key="/This-Is-A-Nice-Page-To-Remember" value="/foo.html" />
/This-Is-A-Nice-Page-To-Remember is the "pretty" URL being requested, and /foo.html is the underlying file that the request is rewritten to that actually handles the request.
This is not an external redirect that "changes" the URL in the browser. You need to actually change the URLs in your HTML source. The rewrite map does not do this for you (and neither is it meant to).
The rewrite map as written probably isn't actually doing anything (missing slash prefix), but if it did then it would presumably result in a 404 since This-Is-A-Nice-Page-To-Remember won't be recognised as a valid page.
To "redirect" old URLs to new
However, if you are changing an existing URL structure then you can implement an additional "redirect" rewrite map to externally redirect requests for the "old" URL to the desired "pretty" canonical URL (essentially the reverse of the above). But you must have already changed the URLs in your HTML source before doing so. This "redirect" rewrite map is simply to preserve SEO and to ensure that any inbound links from other sites are not broken. If you don't change the URLs in your HTML source, then users still see (and are able to copy) the "old" (non-canonical) URLs and every time the user clicks a link they will be externally redirected (doubling the requests to your server and slowing the user).
For example, to implement a "redirect" rewrite map from the "old" to "new" (canonical) URL, create an additional rewrite map:
<rules>
<rule name="CorrectOldURLs" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{OldRedirects:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="https://example.com{C:1}" appendQueryString="False" redirectType="Permanent" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="OldRedirects">
<add key="/foo.html" value="/This-Is-A-Nice-Page-To-Remember" />
</rewriteMap>
</rewriteMaps>
If this is a new site, then this "redirect" rewrite map is not strictly necessary, since the underlying files should never be exposed.
In Summary
Bringing the above two together, we have:
<rules>
<rule name="RewriteMapping" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{Test:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}" appendQueryString="false" />
</rule>
<rule name="CorrectOldURLs" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{OldRedirects:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="https://example.com{C:1}" appendQueryString="False" redirectType="Permanent" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="Test" defaultValue="">
<add key="/This-Is-A-Nice-Page-To-Remember" value="/foo.html" />
</rewriteMap>
<rewriteMap name="OldRedirects">
<add key="/foo.html" value="/This-Is-A-Nice-Page-To-Remember" />
</rewriteMap>
</rewriteMaps>
But to emphasise again, as stated above, you must have manually changed the URLs in the HTML source before implementing this. There is no shortcut here.
Reference:
https://learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/using-rewrite-maps-in-url-rewrite-module

IIS ReWrite rule based on word in url

I am trying to create some rewrite rules (IIS7 ReWrite Module) for drive-by attempts to hack the website.
My problem is that I like to keep my 404 stat clean, but currently it is filled with URL's containing "wp-admin", "fckeditor" and software like that.
I would like to make a ReWrite if the URL contains some specific words somewhere in the URL. So far I made this one that works fine. It look for the word "wp-admin" somewhere in the URL and just rewrites to the homepage.
<rule name="Handle Hacks" stopProcessing="true">
<match url=".*wp-admin.*" />
<conditions logicalGrouping="MatchAll" />
<action type="Rewrite" url="/" />
</rule>
This solution requires a seperate rule for each word. Is there a way to create just one rule that can do the trick with "wp-admin", "fckeditor", "administrator" ect.?
Thanks
You can use OR (symbol |) in your regexp like that:
<rule name="Handle Hacks" stopProcessing="true">
<match url="(wp-admin|fckeditor|administrator)" />
<action type="Rewrite" url="/" />
</rule>

IIS Url Rewrite not working for certain extensions and characters

I am using IIS 7.5 with the Url Rewrite module. Here is my rule.
<rule name="stash.domain.com" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://192.168.5.9:8080/{R:1}" logRewrittenUrl="true" />
<conditions>
<add input="{HTTP_HOST}" pattern="^stash.domain.com$" />
</conditions>
</rule>
Everything works as expected, except if the url contains and extension of ".cs", or if a "+" sign is in the url anywhere.
For example, these don't work
http://stash.domain.com/projects/MDX/repos/medxchange.library/browse/Src/MedXChange.Api/CoreServiceUrls.cs
http://stash.domain.com/projects/MDX/repos/medxchange.library/browse/Src/MedXChange.Api/CoreService+Urls
I get the following response from IIS with those urls.
404 - File or directory not found.
But, these will work, however, the proxy server will return a nice "file not found", which tells me the rule is processed and forwarding requests correctly.
http://stash.domain.com/projects/MDX/repos/medxchange.library/browse/Src/MedXChange.Api/CoreServiceUrls
I suspect the IIS has some top level filtering to either prevent certain file extensions from being served, or attempt to serve them nativelly within IIS, bypassing the rewrite rules. Also, I imagine there are more characters, aside from "+", that cause the rewrite rules to be ignored.
I had this problem too. It turns out the IIS is trying to be helpful and prevent remote users from downloading source code, which was exactly what I was trying to allow!
The fix was to go into Request Filtering and remove all the troublesome entries, although I skipped that and just put this in the web.config:
<system.webServer>
<security>
<requestFiltering>
<fileExtensions>
<clear />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>

Rewriting Subdomains in IIS

I'm having some trouble rewriting some things in IIS
Here is what I'm trying to achieve.
We have a bunch of clients that all need a subdomain. For example
http://clientA.mysite.com needs to be rewritten to http://mysite.com/clientArea/?clientID=1234
Then all content needs to be rewrriten to http://mysite.com/clientArea/XXX
so for example if someone requests http://clientA.mysite.com/example.css , that should be rewritten to http://mysite.com/clientArea/example.css
I cannot for the life of me get this working right.
I think I have to to do this in 2 rules. I think I have the first rule working kindof (page looks whack because it can't get the JS files or CSS files to make it look right)
Here is my first rule to rewrite http://clientA.mysite.com to http://mysite.com/clientArea/?clientID=1234
<rule name="Rewrite Subdomain" stopProcessing="true">
<match url="()" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(?!www)clientA\.mysite\.com$" />
</conditions>
<action type="Rewrite" url="clientArea/?clientID=1234" appendQueryString="true" logRewrittenUrl="true" />
</rule>
My second rule, however, I cannot get to work, so any help with this would be great
<rule name="Rewrite Everything Else after subdomain">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(?!www)clientA\.mysite\.com$" />
</conditions>
<action type="Rewrite" url="{R:0}" />
</rule>
Requesting things like http://clientA.mysite.com/example.js returns a 404 error.
Thanks for the time,
Kyle
If you have dedicated IP number for your site, you can add empty http binding to your site in IIS (right click on your site in IIS > Edit bindings > Add). Then add DNS 'A' record with value: * in your DNS configuration. As a result, every call to your IP will be maintained by your site.
You use a combination in inbound and outbound rewritting rules along with the Application Request Routing Module.
Inbound rule proxies the subfolder to the subdomain content. Outbound rule examines the response and replaces all instances of the subdomain in the response with your subfolder path.

IIS URL rewriting to redirect querystring addresses to MVC style path to preserve old links

I am trying to preserve old links such as index.php?pageid=123 to the now current /accounts/home. No part of the original URL has to be included in the redirect.
I have a big list of old page links and their new address. I thought it would be really simple to say index.php?pageid=123 = /accounts/home but I can't see how to do it. Most of the examples I see are the other way around whereby your site uses query string and you want your URLs to be SEO friendly. I'm using IIS 7.5 to rewrite.
Thanks
Got it sorted and it wasn't that hard really. Just needed to add the query string as a condition.
<rules>
<rule name="accounting" patternSyntax="Wildcard" stopProcessing="true">
<match url="index1.php" />
<conditions>
<add input="{QUERY_STRING}" pattern="page=accounts/accountsmain" />
</conditions>
<action type="Redirect" url="business-services/accounting.aspx" appendQueryString="false" />
</rule>
</rules>

Resources