Removing Server version from Response Headers using URL Rewrite - iis

I have used the information from Remove Unwanted HTTP Response Headers to remove IIS server version from Response Headers.
Add the Server Variable
Create the following outbound rule:
<rewrite>
<outboundRules>
<rule name="Remove Server" patternSyntax="ExactMatch">
<match serverVariable="RESPONSE_SERVER" pattern=".*" />
<action type="Rewrite" />
</rule>
</outboundRules>
</rewrite>
Though the code works fine and URL Rewrite is removing the server version successfully, the integration of the same is screwing up couple of pages in my legacy classical ASPX website as in:
With URL Rewrite:
fa 7 RepCube 8a | Default Measure: 6b Not Set 4e | Size: 84.28Mb
b3 65 c1 130 6 FY2014 bd 78 9 Processed 76 6 Actual 76 10 Jan-14 To Dec-14 1 76 Delete
Without URL Rewrite:
RepCube | Default Measure: Not Set | Size: 84.28Mb
FY2014 Processed Actual 10 Jan-14 To Dec-14 Delete
All the data that is getting generated are from the Classical ASPX page with Server side redirects as in <% tags.
Can you please help me understand what can be the problem with the same?

Related

IIS: 502 when posting multipart/form-data and using ARR

We have a classic ASP.NET web api that is exposing a file upload endpoint. The file upload accepts a multipart/form-data request that holds the file. The format is:
POST https://dev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload
X-API-Key: {{apiKey}}
Content-Type: multipart/form-data; boundary=XXX
--XXX
Content-Disposition: form-data; name="image"; filename="filename.png"
Content-Type: image/png
{{ file bytes }}
--XXX--
We use the following rewriting:
<rule name="Rewrite to dev REST API" enabled="true" stopProcessing="true">
<match url="api/(v[0-9]+/.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" matchType="Pattern" pattern="(dev|dev-testing).appname.com" ignoreCase="true" negate="false" />
</conditions>
<action type="Rewrite" url="https://restapidev.appname.com/api/{R:1}?tenant={C:1}" appendQueryString="true" />
</rule>
So the url is rewritten from: https://dev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload to https://restapidev.appname.com/api/v2/visitors/{{visitorId}}/attachments/upload?tenant=dev
This gives us a response 502.
When hitting the https://restapidev.appname.com/api... url directly, the request is successful.
To diagnose the issue, I am writing the request body to a file:
private async Task SaveRequestBody() {
var req = HttpContext.Current.Request;
using var fileStream = File.OpenWrite($"C:\\temp\\{DateTime.Now:yyyy-MM-dd-HH-mm-ss}-UploadAttachment.txt");
await req.GetBufferedInputStream().CopyToAsync(fileStream);
}
I notice that:
When going through the dev.appname... url:
❌ an empty file is written
When going through the restapidev.appname... url
✅ the full request, including the upload is written to a file
When uploading a file without multipart/form-data (Content-Type: image/png, bytes directly posted in the request body)
✅ the full request, including the upload is written to a file
Application logging seems to indicate that the application "hangs" on reading the request stream.
I have enabled failed request tracing, and noticed this:
At 12:36:37.144: GENERAL_READ_ENTITY_START
At 12:38:37.504: GENERAL_READ_ENTITY_END (2 minutes later!!)
BytesReceived="0", ErrorCode="The I/O operation has been aborted because of either a thread exit or an application request. (0x800703e3)"
FYI: There's a warning REWRITE_DISABLED_KERNEL_CACHE in the trace as well, but succesful requests have this warning as well.
I was not able to add the full log here (due to length restrictions on the post).
So our web application seems to "hang" while reading the request body:
only for an multipart/form-data upload
only when routed through ARR
Is there something that could be misconfigured?

Controller class xxxController could not be found error

I was migrating my web application to another server. Everything works fine except for viewing any uploaded file. It keeps showing the same error whenever I tried to view the uploaded file.
Updated :
eland\app\webroot\upload
Not Working --> <?php echo $this->Html->link(__('<i class="icon-file"></i>'), '../'.ELAND.'/upload/'.trim($rec['Bahanrujukan']['filename']), array('class' => 'btn btn-default btn-small','target'=>'_blank', 'escape' => false)); ?>
eland\app\webroot\img\imgs
Working --> <?php echo $this->Html->link(__('<i class="icon-file"></i>'), '../'.ELAND.'/img/imgs/'.trim($rec['Bahanrujukan']['filename']), array('class' => 'btn btn-default btn-small','target'=>'_blank', 'escape' => false)); ?>
Should I check the plugin or the controller?
It turns out that, the issue was misconfiguration in web.config. During translation from Apache (.htaccess) to IIS (web.config), the 'upload' folder was not granted for access to the webroot.
<rule name="Rewrite routed access to assets(img, css, files, js, favicon)" stopProcessing="true"> <match url="^(img|css|files|js|upload|favicon.ico)(.*)$" /> <action type="Rewrite" url="webroot/{R:1}{R:2}" appendQueryString="false" /></rule>
thanks guys for helping me out!

IIS ReWrite catch .jpg?w=960&h=980

I have created IIS Outbound Rules to rewrite to CDN. Example for .mov files
<rule name="CDN-01-mov" preCondition="CheckHTML" stopProcessing="true">
<match filterByTags="Img, CustomTags" customTags="src" pattern="http(s)?://www.(example.com)(/public)(/uploads)(.*\.mov)" />
<action type="Rewrite" value="https://cdn.example.com/public/uploads{R:5}" />
</rule>
However, I would also like to catch .jpg files. The problem is that the tags with .jpg files in my application are like this:
files/storage/327/9071615039504vishbjwcgbftdy2my1p6.jpg?w=960&h=980
so it has the ?w=960&h=980 part which I don't know how to catch with regex.
How could I make a regex rule to catch .jpg[anything] ?
Thanks
Alex
The character before matching .jpg is R1, the character matching .jpg is R2, and the character string after .jpg is R3.
This is Pattern:
(.*)(.jpg)(.*)
Here is for your reference: Regular Expression Language - Quick Reference

IIS 8.5 MVC5 Client Cache is ignored

TL;DR - I want the server (IIS 8.5) to return 304 not modified for the CSS and JS bundles.
I've been unable to get IIS 8.5 to honor the clientCache settings in web.config. No matter what I do, I can't seem to get it to cache the static content. This is a MVC5 app in VS2013. I've got all the static files in a folder "Assets".
The request looks like:
http://someserver/AppName/Assets/mainjs?v=FNj_9ZPAbYVAQsyDo2F8XUnWv5NQpY4iX2RGu4NpJ5g1
Attempt #1, place a new web.config in the Assets folder with the following:
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
Attempt #2: place this following configuration in the root web.config
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
</staticContent>
Attempt #3: trying setting the cache using the location tag
<location path="Assets">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
</staticContent>
</system.webServer>
</location>
Here are the things I've tried in IIS 8.5 manager. Under the Default Web Site/TestApp
HTTP Requeset Headers, Set Common HTTP Headers, check "Expire Web Content" "After 365 Day(s)".
Apply the same setting to the "Assets" folder
I've tried these steps each on their own and all together and every other which way. No matter what, it won't add the max-age value to Cache-Control.
For each of these, the browswer returns 200 responses for the CSS and JS bundles. I cannot get the server cache the content coming from the Assets folder.
Cache-Control:private
Content-Encoding:gzip
Content-Length:22591
Content-Type:text/css; charset=utf-8
Date:Mon, 02 Feb 2015 21:49:49 GMT
Expires:Tue, 02 Feb 2016 21:49:49 GMT
Last-Modified:Mon, 02 Feb 2015 21:49:49 GMT
Persistent-Auth:true
Server:Microsoft-IIS/8.5
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Check the individual files of the bundle. What do the files look like when you turn off optimizations? After you register your Bundles make a call to :
BundleTable.EnableOptimizations = (!HttpContext.Current.IsDebuggingEnabled);
OR
BundleTable.EnableOptimizations = false;
It could be that each file is coming back with a not modified. Does the status change when you refresh while in a debug session?

Server.MapPath() with IIS URL Rewrite Module 2.0

I have a website in IIS, with a legacy classic asp application configured as a sub app.
I'm basically trying to create URL rewrite rules so that I don't have to change all of the relative URL's in the code.
e.g. URLS's such as "/themes/somedirectory" should be mapped to "/legacy/themes/somedirectory"
Using the URL Rewrite Module 2.0 I have a URL rewrite rule configured as follows:
<rule name="Reroute themes">
<match url="^themes.*" />
<action type="Rewrite" url="/legacy/{R:0}" />
</rule>
This works fine when navigating to the URL. However when using Server.MapPath(), it is not applying the rewrite rule.
Is Server.MapPath() actually supposed to take this into account? If not, how should I go about re-routing the application without modifying the code?
I was looking for the same thing so I gave it a try in a test app. It appears that Server.MapPath() does not acknowledge URL Rewrite Module rules.
Here is how I tested using an empty web project (Razor syntax):
Rewrite rule:
<system.webServer>
<rewrite>
<rules>
<rule name="Rewrite rule1 for test1">
<match url="^test1(.*)" />
<action type="Rewrite" url="{R:1}" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
cshtml:
<p>
The URL for this page is #Request.Url.AbsoluteUri .
<br />
MapPath of /test1 is #Server.MapPath("~/test1")
<br />
MapPath of / is #Server.MapPath("~/")
</p>
I hit http://localhost/, then http://localhost/test1. The results were:
The URL for this page is http://localhost/ .
MapPath of /test1 is c:\src\temp\test1
MapPath of / is c:\src\temp\
So looks like mappath is basically taking System.AppDomain.CurrentDomain.BaseDirectory (or something similar) and combining it with the relative URL. On a side note, I have separately confirmed that MapPath() takes into account 1 level of virtual directory, but not a 2nd (ie. virt pointing to another location that also has a virt defined).
I just had this problem, and for now am going with create a special MapPath variant that corresponds to my rewrite rule.
So either something like this:
string MapTheme(string themeName)
{
return Path.Combine(Server.MapPath("/legacy"), themeName)
}
Or, if you prefer:
string MapThemePath(string themeUrl)
{
Match m = Regex.Match("^themes/(.*)");
if (!m.Success)
throw new ArgumentException();
string themeName = m.Groups[1].Value;
return Path.Combine(Server.MapPath("/legacy"), themeName)
}
Or generalize:
string MyMapPath(string url)
{
Match m = Regex.Match("^themes/(.*)");
if (m.Success)
{
string themeName = m.Groups[1].Value;
return Path.Combine(Server.MapPath("/legacy"), themeName)
}
else if (itsAnotherSpecialRewriteCase)
{
return doSomeSimilarTransformation();
}
// ...
else
{
// Handle non-rewritten URLs
return Server.MapPath(url);
}
}
I don't especially like this, because it violates "do not repeat yourself".

Resources