Is it possible to get the current machine name in IIS 7.5 Url Rewrite Module Rules? - iis

The HTTP_HOST and SERVER_NAME server variables give me the host name from the HTTP request (which can be an IP address or the load-balanced DNS based on how the request was made). I could not find a server variable that will give me actual machine name (i.e., the value of the COMPUTERNAME environment variable).
I am trying to set-up some redirection rules on a server-farm and there are some rules based on what the current machine name is (e.g., internal machines have int in their name). I don't want to create separate rules for each machine, and instead want to have some conditional logic based on the current machine name. I cannot seem to find a way to get hold of the machine name.
Any ideas?

In IIS7 The computer name isn't one of the built-in server variables. However all is not lost, with a bit of work using a custom UrlRewrite provider you can surface your machine name in a rewrite rule.
Scott Forsyth has actually built something like this already and has written a blog post describing its use, and provided the source and a pre-built binary + installer:
URLRewrite ServerNameVariable Provider
For the sake of preserving this information in the event of that article disappearing here are loosely the steps:
Start by creating a new class library project in Visual Studio. You can find the steps to do this here:
Developing a Custom Rewrite Provider for URL Rewrite Module (IIS.NET)
They are in essence (in case the link dies):
Create a Class Library project and call it something like ServerNameProvider. You need to make sure the project is a .NET 2.0 or 3.5 project. IIS7.5 managed code support still targets the 2.0 runtime.
Rename the default Class1.cs file to a name that reflects the provider purpose, for example: ServerName.cs - and just make sure the class name in the source reflects this as well.
Add a reference to: %ProgramFiles%\Reference Assemblies\Microsoft\IIS\Microsoft.Web.Iis.Rewrite.dll.
In the project properties create a strong name key (on the signing tab)
Add a post-build event to install the provider assembly in your dev PC GAC (just for testing):
CALL "%VS90COMNTOOLS%\vsvars32.bat" > NULL
gacutil.exe /if "$(TargetPath)"
Note, if using Visual Studio 2010 then the environment variable %VS90COMNTOOLS% should be changed to %VS100COMNTOOLS%.
Open up the ServerName.cs file and make sure your class implements the Microsoft.Web.Iis.Rewrite.IRewriteProvider interface:
using System.Collections.Generic;
using Microsoft.Web.Iis.Rewrite;
namespace ServerNameVariable
{
public class ServerName : IRewriteProvider
{
public void Initialize(IDictionary<string, string> settings,
IRewriteContext rewriteContext)
{
}
public string Rewrite(string value)
{
return System.Environment.MachineName;
}
}
}
Build the project. On your local PC the assembly will be installed into the GAC.
Register the provider with IIS:
appcmd.exe set config -section:system.webServer/rewrite/providers /+"[name='ServerNameVariable',type='ServerNameVariable.ServerName, ServerNameVariable, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5854ff76fb5c07af']" /commit:apphost
Make sure the PublicKeyToken value in the command line above matches your assembly's public key token. You can extract that value by doing sn.exe -T <assemblyfile.dll>, for example:
e:\AppDev\..bin\Debug> sn.exe -T ServerNameVariable.dll
Microsoft (R) .NET Framework Strong Name Utility Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.
Public key token is 5854ff76fb5c07af
The next thing to do is use your new provider in a rewrite rule, for example, here's the example Scott gave which is an outbound rule:
<outboundRules>
<rule name="Set Custom Header" enabled="true">
<match serverVariable="RESPONSE_X_Machine_Name" pattern=".*" />
<action type="Rewrite" value="{ServerNameVariable:}" />
</rule>
</outboundRules>
And here's a simple inbound rule that redirects to google.com if the machine name is BOB:
<rewrite>
<rules>
<rule name="TestServerVariableProvider"
enabled="true"
stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{ServerNameVariable:}" pattern="BOB" />
</conditions>
<action type="Redirect"
url="http://google.com"
appendQueryString="false"
redirectType="Found" />
</rule>
</rules>
</rewrite>

Related

relative paths not functioning after site files uploaded to server

I developed a website locally using "localhost" and created all the site links, buttons, etc using a relative path structure. My server code is written in Node.js/Express. I am also using .ejs for a template engine...therefore all my server webpages are in a folder called "views/pages".
Using this structure, for example, I have a button with a link coded as:
Enter Site
On my development 'localhost' machine this was sufficient to call the '_landing' route in my server script which would then render the proper page to be served...without any difficulty. The server code would read something like this:
app.get('/', function (req, res) {
res.render('pages/_splash');
});
app.get('/_landing', function(req, res) {
res.render('pages/_landing', {user_stat: _subscriber});
});
Now I have uploaded my site files to a Windows server using Plesk software. The site files and folders are located in a directory named "httpdocs". It now seems my relative path links are broken. Using the button link above again as an example for some reason it now wants to route to "https://example.com/_landing"...which is obviously not correct. Why does it seem the relative path now seems to ignore the route call in Node.js...?
Any advice greatly appreciated, I am having extreme difficulty posting my site online due to a myriad of undocumented problems like this...posting a request to my server support will be useless since they do not respond to "coding issues". I thank you in advance.
For anybody that may be interested after several weeks I was able to determine the problem here. I eventually enlisted Plesk support in an effort to solve this issue. It was confirmed to me by a Plesk technician that my described issue was caused by a bug in the Plesk software platform.
The solution to resolve the bug was to insert some additional code in the 'web.config' file as follows:
<rewrite>
<rules>
<remove name="startup-file for site #1" />
<rule name="startup-file for site #1">
<match url="/*" />
<conditions />
<serverVariables />
<action type="Rewrite" url="/test2.js" />
</rule>
</rules>
</rewrite>
This code is to appear in the 'web.config' file AFTER "/httpErrors" AND WITHIN "/system.webServer"...the 'test2.js' should be set to the JS script file for your domain.

web.config causes HTTP 500 issue with virtual directory in IIS

I'm fairly new to IIS so apologies if this is a basic question.
I have an IIS config serving an internal company website (php instead of asp.net). The prod version of the website is at the 'Default Web Site' level and I've got demo and test versions of the website mapped as virtual directories. The demo and test version are essentially copies of the prod directory. I've noticed the with the web.config copied to these VDs, I get an error 500 on the root url for the VD only. I.E. main website is https://mainwebsite.com and works fine but https://mainwebsite.com/demo/ doesn't work while https://mainwebsite.com/demo/index.php works fine.
The web.config file is pretty basic:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
</handlers>
<defaultDocument>
<files>
<add value="index.php" />
</files>
</defaultDocument>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:03:00" />
</staticContent>
</system.webServer>
</configuration>
Moving the web.config file out of the way in the VD resolves the issue. Even though the files are identical, I wouldn't think that the file should cause a conflict as my understanding is that IIS supports multiple web config files.
Although I have a workaround in place by renaming or deleting the file, I am wondering if there's a way to keep the file in place without it causing this error.
Thanks to Panama Jack in the comments, I was able to resolve my issue.
I got this response with detailed errors:
Error Summary
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
And further down:
Config Error
Cannot add duplicate collection entry of type 'add' with unique key attribute 'value' set to 'index.php'
To resolve, I simply commented out this line in the web.config XML:
<add value="index.php" />
I'm sure there's a better way to approach this but for now, this gets me my answer and also how to get more info from IIS when the logs are not useful.
if you create a virtual directory to another web root
web.config will cause this (personally I think the location of this file is totally insane.. mixed with htm and images etc. )
Replicate the directory somewhere else without the web.config file/excluding it..then point the virtual directory there.. & have a task set up to copy newer files over..

IIS File Download without Extension

I've got a .NET Web API 2 application, I've hooked up the api to send me a file id and from there I get the unique file from the server.
Example:
Download
I need it to be a unique id since there could be multiples of the file in the repo. However, when I try to click the download button I get a :
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I was thinking a re-write rule might be a good action, but I dont really want to rewrite it, i just want to allow anything /api/attachment no matter what the rest.
I've already got one rewrite rule since my page is a single-page-application to direct responses to the Default.cshtml like:
<rewrite>
<rules>
<rule name="Default" stopProcessing="true">
<match url="^(?!Lib|api|Assets|Views|Directives|Services|Controllers|signalr).*" />
<action type="Rewrite" url="Default.cshtml" />
</rule>
</rules>
</rewrite>
any thoughts on best way to achieve this?
I was able to resolve by creating an iframe and setting the src to the download like:
$("body").append('<iframe name="downloadFrame" id="download_iFrame" style="display:none;" src="" />');
and then in the C# I set the header like:
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

Rewriting custom tag attributes using IIS Url Rewrite 2.0 and ARR

I've developed a custom grid control that uses data-* attributes to configure how the grid is supposed to work (in a similar vein to how Bootstrap data API components work. For a particular deployment, I'm having to proxy my web application into another web application using IIS and Application Request Routing (ARR) + URL Rewrite. The proxying part is all done, I'm currently trying to configure the outbound rules for rewriting urls to match. For instance, I currently have rules set up such as:
Rewrite HTTP redirects by updating the Location: header.
Rewrite Html content for URIs in standard tags (e.g., A, Area, base, etc.)
Rewrite Css content for URI's that are relative (e.g. /cassette.axd -> /blog/cassette.axd).
The last issue I am having, is getting the URL rewrite module to accept my urls in data attributes, e.g., if my grid is such like:
<table data-grid data-query="/api/users/">
Should be rewritten as
<table data-grid data-query="/blog/api/users/">
I stress that all other tags, such as <a href and <img src work as expected and even a custom <property value tag is correctly rewritten. Just seems to by hypenated attributes.
I've tried adding a <customTags> section, with my custom tags in:
<customTags>
<tags name="Bootgrid">
<tag name="table" attribute="data-query" />
<tag name="table" attribute="data-update" />
<!-- This next tag WORKS -->
<tag name="property" attribute="value" />
</tags>
</customTags>
However, the above is not matching any attributes that have a hyphen. Not sure if this is actually solvable or not because I can't see anything in IIS configuration to set these.
Also annoyingly once you've created a set of Custom Tags in IIS, you can't seem to edit them again. :-/
I had the same issue, and it appears (although not confirmed by Microsoft) that IIS cannot handle a custom tag that contains a -
A work around that worked for me was to use another outbound Rule. In this example I am attempting to replace the data-zoom-image attribute within an img tag (You will need to replace the <img with <table and data-zoom-image with data-query in both the "match" and "action"
<rule name="RewriteRelativePathsCustomTags1" preCondition="IsHtml" enabled="true">
<match filterByTags="None" pattern="<img ([^>]*)data-zoom-image="(.*?)"([^>]*)>" />
<action type="Rewrite" value="<img {R:1}data-zoom-image=&quotYOUR VALUE TO REWRITE i.e /blog{R:2}"{R:3}>" />
</rule>
<preConditions>
<preCondition name="IsHtml">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
Hope this helps
ARR on IIS seems to have issues with tags that include attributes with a dash (-) in them.
Updating to v3.0.1952 seems to have solved the issue for me, but I'm still investigating.
Rather belated, but this was fixed back in 2015 in the Release To Web version (2.0.1952):
IMPORTANT - Changes in this release
Windows 10 and Windows Server 2016 Support - It is now possible to install URL Rewrite Module 2.0 on Windows 10 or Windows Server 2016 with this release
Custom attributes containing dashes are now supported. This is required as HTML 5 has the following rules for determining HTML attribute names: http://www.w3.org/TR/html-markup/syntax.html#syntax-attributes
Incorporates Hotfix for URL Rewrite 2.0 (June 2014) as in KB2974666

Exception setting Http response header 'Glimpse-RequestID'

I'm attempting to get Glimpse running on a server. The way that IIS is set up here is that a site is mapped to what appears to be an external domain, but in fact is a local IIS project. The windows "hosts" file maps the "site.foo.com" domain to the 127.0.0.1, and "site.foo.com" is then added as a binding to the site in IIS. I mention this because it's almost certainly important, as I don't know if it means it appears as a local or remote request, even from the browser on the local machine
To get the Glimpse icon to even appear from requests on the local machine, I updated the web.config ignore some of the runtime policies (as the log was complaining about those):
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<!-- If you are having issues with Glimpse, please include this. It will help us figure out whats going on. -->
<logging level="Trace" />
<runtimePolicies>
<ignoredTypes>
<add type="Glimpse.AspNet.Policy.LocalPolicy, Glimpse.AspNet"/>
<add type="Glimpse.Core.Policy.StatusCodePolicy, Glimpse.Core"/>
<add type="Glimpse.Core.Policy.ContentTypePolicy, Glimpse.Core"/>
<add type="Glimpse.Core.Policy.ControlCookiePolicy, Glimpse.Core"/>
</ignoredTypes>
</runtimePolicies>
</glimpse>
The icon now appears, but nothing happens when I click it, and the following appears in the log
2013-04-15 13:10:00.7978 | ERROR | Exception setting Http response header 'Glimpse-RequestID' with value '6991f828-b716-40b1-9362-56dfd64b6440'. | System.Web.HttpException--Server cannot append header after HTTP headers have been sent.-- at System.Web.HttpResponse.AppendHeader(String name, String value)
at Glimpse.AspNet.AspNetFrameworkProvider.SetHttpResponseHeader(String name, String value)
any ideas what I need to look at next?
thanks

Resources