I'm running a website with IIS8 on Windows Server 2012. I'm trying to determine what's causing high CPU usage by IIS (frequently 50% or more CPU usage by IIS). Server receives about 40 total requests per second throughout the day, but probably only 1-2 URLs per second that require processing.
I enabled Request Tracing and found that some RewriteModule requests are taking over 100 seconds (!) to complete. I'm having trouble determining how this is possible on a machine with more than sufficient hardware. The exact same URL structure is processed via mod_rewrite on Apache in less than a second.
An example URL would be like this:
http://<domain-name>/Product/<Parent-Category>/<Child-Category1>/<Child-Category2>/<Child-Category3>/<Product-Name>
The accompanying rewrite rule is:
<rule name="Rule" stopProcessing="true">
<match url="^Product/([^/\?]+)/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?([^/\?]+)?/?[\?]?(.+)?$"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="/Product/index.php?a={R:1}&b={R:2}&c={R:3}&d={R:4}&e={R:5}&f={R:6}&{R:7}" appendQueryString="true"/>
</rule>
Is there something in the way that I'm defining the match URL that's causing high processing time? Some of the matching urls contain a high number of characters if they utilize many parent/child categories (up to 5, typically 3-4).
Problem is definitely in your regexp. Best way is try to split it to different more specific patterns.
If it is not the case, this rule should keep the same functionality and work faster:
<rule name="Rule" stopProcessing="true">
<match url="^Product/([^/]+)/?([^/]+)?/?([^/]+)?/?([^/]+)?/?([^/]+)?/?([^/]+)?"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="/Product/index.php?a={R:1}&b={R:2}&c={R:3}&d={R:4}&e={R:5}&f={R:6}" appendQueryString="true"/>
</rule>
I removed unnecessary \? checks in your regexp, because patter inside <match url is checking URL without query string, so, it is redundant to have ? checks in your regexp.
I checked on my PC and it works definitely faster, but you need to double check that it remains the same functionality
I did extensive testing and changed the rule to the following. This resulted in CPU dropping to 1% and the previous 100-second completion time dropping to roughly 50ms.
I still don't understand how this is possible - this is an 4 CPU/8-core machine with 48GB of RAM, and IIS8 took 100 seconds to pull apart a 70 character string and compare it to the previous regex. Unless the previous example somehow created a near infinite loop, I don't see how it could possibly be that slow.
New Rule:
<rule name="Rule" stopProcessing="true">
<match url="^Product/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+)?[/]?(.+)?$"/>
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="/Product/index.php?a={R:1}&b={R:2}&c={R:3}&d={R:4}&e={R:5}&f={R:6}&{R:7}" appendQueryString="true"/>
</rule>
Related
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
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>
This question already has answers here:
IIS URL Rewrite ASP
(2 answers)
Is it possible to do friendly url (url rewriting) in classic asp?
(7 answers)
Closed 4 years ago.
Good Morning,
I've been looking into making my product and category URL's SEO friendly by using IIS's URL Rewrite option, however I'm struggling and need some advice.
I'm trying to get the following implemented:
http://www.dibor.co.uk/Product.asp?ProductId=Y054&title=salle-de-bain-dustbin
TO
http://www.dibor.co.uk/prod/Y054-salle-de-bain-dustbin
Please can someone help me on creating the information that needs to be submitted into the URL Rewrite Rule?
From the look of it I need to have:
- Pattern
- Redirect URL
I think this should be added to the web.config
<rules>
<clear />
<rule name="Products rewrite" stopProcessing="true">
<match url="^prod/(.*?)\-(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/Product.asp?ProductId={R:1}&title={R:2}" />
</rule>
</rules>
You could make the rule more specific by adding stuff like:
^prod/(Y[0-9]{3})\-(.*)
But only if you're certain that the product ID is in the format Y000
Change the default 404 error page to 404.asp and parse the url to return the correct information. There is a good example here IIS URL Rewrite ASP
I have a Windows Server 2012 instance running IIS 8.
We are hosting a .NET 4.0 website trying to use an outbound rewrite rule to fetch CDN assets.
The presence of the outboundRules tag in the web.config seems to throw the site into an endless redirect loop. The site performs perfectly without the outboundRules tag. I have included the actual rewrite rule we are using but even including the outboundRules tag with nothing in it can cause the site to end up non responsive.
We have confirmed that static compression is not enabled for the site which is what a few other posts around the web have referenced but that does not seem to resolve our situation.
<outboundRules>
<preConditions>
<preCondition name="ExcludeAXD">
<add input="{URL}" pattern=".axd" negate="true" />
<add input="{URL}" pattern=".asmx" negate="true" />
<add input="{URL}" pattern=".ashx" negate="true" />
</preCondition>
</preConditions>
<rule name="CDNRule" enabled="true" preCondition="ExcludeAXD"
stopProcessing="true">
<match filterByTags="Img, Input, Script, Link"
pattern="(^.*?(?=/mymediafoldercontainingassets))(.*)" />
<action type="Rewrite" value="{R:1}http://subdomain.mycdn.com{R:2}" />
</rule>
</outboundRules>
Any help would be greatly appreciated,
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.