Adding expire headers to Web.Config file - iis

I'm looking to add expire headers to my website so I can set a cache time for the files.
I've found the following the example, but I'd like to set it to only cache JPG, PNG, GIF, JS and CSS files if possible?
<system.webServer>
<staticContent>
<clientCache cacheControlMaxAge="14.00:00:00" cacheControlMode="UseMaxAge"/>
</staticContent>
</system.webServer>
Thanks for any help!

What you can do is to create web.config files in the folders where your files are. (You might have folder such "Images" for images and "Js" for javascript files, "Css" for style sheets... etc.) Then, you paste yor code in those files. By doing that you apply your cache settigs to all files in those folders, regardless of the file type. This is more flexible method than applying cache settings to a particular file extension.

IIS does NOT support dynamic expires headers for static content.
You can add a static expires header this way:
<system.webServer>
<staticContent>
<clientCache httpExpires="Sun, 29 Mar 2020 00:00:00 GMT" cacheControlMode="UseExpires" />
</staticContent>
</system.webServer>
Source:
The Official Microsoft IIS site
There is a similar question here:
IIS 7.5 How do you add a Dynamic HTTP Expires Header

As already pointed out using another web.config in the specific folder is probably the best option.
However you can override the cache control header with and outbound rewrite rule:
<system.webServer>
...
<rewrite>
<outboundRules>
<rule name="RewriteCacheControlForHTMLFiles" preCondition="jsFile">
<match serverVariable="RESPONSE_Cache_Control" pattern=".*" />
<action type="Rewrite" value="max-age=86400" />
</rule>
<preConditions>
<preCondition name="jsFile">
<add input="{REQUEST_FILENAME}" pattern="\.js$" />
</preCondition>
</preConditions>
</outboundRules>
...

If you want to cache specific Items I would go the route of doing this programatically. You could use the following code to get you going. It's from microsoft, i just brought it over so you don't have to go find it. http://msdn.microsoft.com/en-us/library/ff477235.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.Caching;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click1(object sender, EventArgs e)
{
ObjectCache cache = MemoryCache.Default;
string fileContents = cache["filecontents"] as string;
if (fileContents == null)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration =
DateTimeOffset.Now.AddSeconds(10.0);
List<string> filePaths = new List<string>();
string cachedFilePath = Server.MapPath("~") +
"\\cacheText.txt";
filePaths.Add(cachedFilePath);
policy.ChangeMonitors.Add(new
HostFileChangeMonitor(filePaths));
// Fetch the file contents.
fileContents = File.ReadAllText(cachedFilePath) + "\n"
+ DateTime.Now.ToString();
cache.Set("filecontents", fileContents, policy);
}
Label1.Text = fileContents;
}
}

Related

IIS: Rewrite / Redirect [duplicate]

I do my best to scan the forum for help to make a web.config to do a Rewrite of this kind of url
domain.com/default.asp?id=3&language=2
My hope is that this can be
domain.com/en/service
where language=2 is "en"
and id=3 is page "Service" (this name exist in a mySQL)
I can only find example that do it vice versa...
Like this
<rewrite>
<rules>
<rule name="enquiry" stopProcessing="true">
<match url="^enquiry$" />
<action type="Rewrite" url="/page.asp" />
</rule>
</rules>
</rewrite>
I would like it to be something like this... I know this isn't correct, but maybe explains my problem.
<rewrite>
<rules>
<rule name="enquiry" stopProcessing="true">
<match url="^default.asp?id=3&language=2$" />
<action type="Rewrite" url="/en/serice" />
</rule>
</rules>
</rewrite>
If you want to use regular expressions you could do something like this
<rule name="RewriteUserFriendlyURL1" stopProcessing="true">
<match url="^([^/]+)/([^/]+)/?$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="default.asp?language={R:1}&id={R:2}" />
</rule>
This would rewrite "domain.com/en/service" as "domain.com/default.asp?language=en&id=Service", or "domain.com/2/3" as "domain.com/default.asp?language=2&id=3"
To change the 2 to en and the 3 to service, along with all the other options though I think you would need a separate rule for each permutation, or have some sort of logic within your asp pages to read your querystring variables and send the corresponding values to your SQL queries. Note also that the parameters in the friendly url appear in the same order and the querystring variables in the rewritten URL, although this shouldn't really be an issue. If someone tries to access the page with the original "unfriendly" url they will find what they are looking for, whichever way round they enter the querystring variables.
Please note, I didn't actually hand code the rule above, I generated it with the URL Rewrite module in IIS manager - it makes life a lot easier
Also note, as discussed with my namesake in the other answer, this only applies to IIS7 and above
I have done this in Classic ASP using custom error pages and this seems to be the best way unless you use some sort of third party component installed on the server.
To do this, in IIS (or web.config) you need to set up 404 errors to go to a specific custom error Classic ASP page (eg. 404.asp).
In this custom error page you first need to check to see if the URL is valid. If it is you can Server.Transfer to the correct page, return a 200 response code, and parse the URL there to convert the URL to the values needed for the database lookup, etc. If it's not a valid URL then you show a custom error page and return a 404 response code.
The code to check for a valid URL and to retrieve the URL parameters will vary greatly depending on your URL structure. But to find the URL requested on the custom 404 error page you have to look at the querystring, which will be something like "404;http://domain.com:80/en/service/".
Here's some sample code that gets the parameters from the requested URL:
Dim strUrl, intPos, strPath, strRoutes
strUrl = Request.ServerVariables("QUERY_STRING")
If Left(strUrl, 4) = "404;" Then
intPos = InStr(strUrl, "://")
strPath = Mid(strUrl, InStr(intPos, strUrl, "/") + 1)
If strPath <> "" Then
If Right(strPath, 1) = "/" Then strPath = Left(strPath, Len(strPath) - 1)
End If
strRoutes = Split(strPath, "/")
'Here you can check what parameters were passed in the url
'eg. strRoutes(0) will be "en", and strRoutes(1) will be "service"
End If
And here's how you can setup custom error pages in the web.config (rather than in IIS):
<?xml version="1.0"?>
<configuration>
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" subStatusCode="-1" responseMode="ExecuteURL" path="/404.asp" />
</httpErrors>
</system.webServer>
</configuration>

IIS Url Rewrite: How to handle picture source srcset?

I have a site I'm reverse proxying using IIS UrlRewrite. So far I've had a fairly easy time of it thanks to Paul Cociuba's three articles on Microsoft Tech Community.
My current challenge is with a group of urls in a <picture><source srcset which are, heavily abbreviated,
<source srcset="/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-5.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 1400w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-6.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 2000w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-7.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 2800w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-1.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 350w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-2.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 460w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-3.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 700w,
/a/b/c/d/e/en/g/h/thumb%20classes%202020_SX_MX.component.crop-3x2-4.ts=1592419103694.jpg/a/c/d/oceania/au/en/g/jcr:a/root/z_1_col/z_4_col/image_1558468008 920w"
media="(max-width: 768px)"
sizes="(max-width: 768px) 100vw">
How do I convert all of the paths that begin with /a/b/c to https://othersite/a/b/c? At worst I could perhaps write a regular expression that captures a fixed number of paths (say 7) and then rewrites them with {R:1} through {R:7} but I'm not sure at this point whether the number of items in each srcset is fixed.
Also, do I need to create a custom tag so as to match the <source srcset=?
This worked and I'm rather surprised. I'm still not getting the response I'm expecting from the page (some of the images still aren't drawing), but at least the HTML appears to be correct.
First up, I've declared a custom tag
<customTags>
<tags name="sourceSrcset">
<tag name="source" attribute="srcset" />
</tags>
</customTags>
Then I've written an outbound rule to use it
<rule name="source srcset" preCondition="ResponseIsTextHtml">
<match filterByTags="CustomTags" customTags="sourceSrcset" pattern=",?\/(a\/b\/\S+\s\d+w)" />
<action type="Rewrite" value="https://othersite/{R:1}" />
</rule>
In case you're wondering, ResponseIsTextHtml has a brother called ResponseIsTextAnything and these are declared as
<preCondition name="ResponseIsTextHtml">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
<preCondition name="ResponseIsTextAnything">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/(.+)" />
</preCondition>

Installshield changing <clear /> to <clear></clear> and breaking the service

My source xml looks like this :
<connectionStrings>
<clear />
<add name="StrConn" providerName="SQLNCLI10"
connectionString="Server=dbserver;Database=db;User Id=user;Password=pass;" />
</connectionStrings>
Notice the seemingly innocent <clear /> tag.
Once I've imported this xml, and made changes to the xml file i.e: the connection string. All single tags in the document like <add /> or <clear /> are rewritten to long form eg: <clear></clear> and this prevents my service / app from even running.
It seems crazy since ultimately it seems like valid XML, but yeah it dies with an unknown fault exception, but when replacing the clear tags to all be <clear /> and not <clear ></clear> it works.
How can I prevent installshield from transforming these tags?
Are you using the 'update xml' feature? Try using the 'udpate text file' instead. That's a bit ugly to use for xml files but it works (we've been using it before the update xml feature was introduced)

iis 7.5 url rewrite -not processing percent '%' symbol

I imported rules from IIRF into IIS URL Rewrite, and most seemed to work fine. I just noticed tho that some urls have percent symbols in them (trying to redirect some bad inbound links, with percent encoded characters in them). The regex seems to not work when the percent is in there, so I assume it is trying to interpret is as a command or something. Can't find any documentation on this, anyone know?
The accepted answer didn't work in my case, but I discovered a different way to setup the rewrite rule. This will do a 301 redirect.
Requested URL: http://www.shuttercontractor.com/m/vinyl-%E2%80%8Bshutters.aspx
Target URL: http://www.shuttercontractor.com/m/vinyl-shutters.aspx
<rule name="301 Redirect to vinyl shutters category" stopProcessing="true">
<match url="." ignoreCase="false" />
<action type="Redirect" redirectType="Permanent" url="m/vinyl-shutters.aspx" />
<conditions>
<add input="{UNENCODED_URL}" pattern="m/vinyl-%[Ee]2%80%8[Bb]shutters\.aspx" ignoreCase="false" />
</conditions>
</rule>
Basically, the match will work on any URL, and we use a condition with the UNENCODED_URL server variable to ensure the pattern matches before redirecting.
appears that the rewrite rules already undo the url encoding, so it no longer sees a %3E as that, but instead as a '<'.. so using a > in place of %3E does the trick. Now, to go fix a bunch of urls. argh.
Edit:
Also, if you hand edit the web.config (versus using the UI editor), you will need to use & lt ; for the < symbols. It's probably best to use the UI to avoid confusion.

Can I make IIS add (inject) HTML to every page it serves?

I would like to add some HTML to every page that our IIS 6 server serves. It's serving static HTML for the most part. Is this something IIS or an extension can do? I would need some control over how and where the HTML is injected, in this case before the tag. Thanks for your suggestions!
Natively I believe the only thing you can do is insert a document footer (on the Documents tab).
If you're familiar with ASP.NET, you could write a HTTP Response Filter to do that.
Read this article by Milan Negovan.
The HttpResponse class has a very useful property:
public Stream Filter {get; set;}
MSDN provides a helpful description of
this property: "Gets or sets a
wrapping filter object used to modify
the HTTP entity body before
transmission." Confused? In other
words, you can assign your own custom
filter to each page response.
HttpResponse will send all content
through your filter. This filter will
be invoked right before the response
goes back to the user and you will
have a change to transform it if need
be.
This could be extremely helpful if you
need to transform output from "legacy"
code or substitute placeholders
(header, footer, navigation, you name
it) with proper code. Besides, at
times it's simply impossible to ensure
that every server control plays by the
rules and produces what you expect it
to. Enter response filters.
The Filter property is of type
System.IO.Stream. To create your own
filter you need to derive a class from
System.IO.Stream (which is an abstract
class) and add implementation to its
numerous methods.
I was able to inject some CSS before the using the URL Rewrite Module, via an outbound rule:
<rewrite>
<rules>
<outboundRules rewriteBeforeCache="true">
<rule name="Add custom CSS" preCondition="IsHTML">
<match filterByTags="None" pattern="</head>" />
<action type="Rewrite" value="<link rel="stylesheet" href="/path/to/custom/styles_override.css"></head>" />
</rule>
<preConditions>
<preCondition name="IsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rules>
</rewrite>
You should be able to do the same with html content, instead of css...
In IIS proper, you can add a footer, which is great for a copyright line, or similar. If you want more control, to truly "inject", I would create an HTTP Handler (.NET) that handles .html requests and adds what you need.
If you are "old school", use ISAPI filters instead. Too much work for my tastes.

Resources