IIS static compression: favour minimising bandwidth over latency? - iis-7.5

If I configure IIS to use data compression for static files, the first client usually receives uncompressed content, with later clients getting compressed content. Presumably IIS compresses the file in the background and caches it for later requests.
However, I'd prefer the first client to also receive compressed content. That is: I'd prefer to trade latency for bandwidth. Is there any way I can configure IIS to do this?

Well, it actually works a little bit differently. IIS is not compressing the file in the background but it has a threshold to decide whether is should compress the content at all. This prevents it from using CPU resources and cache store for infrequently requested content. By default IIS will only compress content when it receives two requests for that content within 10 seconds.
You can change these defaults by changing the frequentHitThreshold and frequentHitTimePeriod attributes in the <serverRuntime /> element in web.config (see configuraton reference on iis.net). I've not tested it but I expect that just setting frequentHitThreshold to 1 will give you the desired result.
<configuration>
<system.webServer>
<serverRuntime frequentHitThreshold="1" />
</system.webServer>
</configuration>
Hope this helps.

Related

How to Use eTag on IIS for text/html Pages

I have a website which sits on a non-public domain and is delivered via a proxy through on a different domain. We're having some trouble with caching of content - this is an Umbraco site and making changes updates the pages if you hit the domain directly, but not through the proxy.
I've been informed that the proxy honours response headers and setting an eTag would fix the issue. Having looked into this I can see that IIS sets the eTag by default, and I can see this is working on static content i.e. .js, .css files like so:
However, if I visit a page on the site, for example /uk/products/product I don't see the eTag header.
Is this expected behaviour, should it only be working with those static content files or can I set this on the page to tell the proxy that it should recache?
The ETag HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed. Additionally,etags help prevents simultaneous updates of a resource from overwriting each other ("mid-air collisions").
If the resource at a given URL changes, a new Etag value must be generated.
Static content does not change from request to request. The content that gets returned to the Web browser is always the same. Examples of static content include HTML, JPG, or GIF files.
IIS automatically caches static content (such as HTML pages, images, and style sheets), since these types of content do not change from request to request. IIS also detects changes to the files when you make updates, and IIS flushes the cache as needed.
to enable caching in iis you could use iis output caching feature:
1)open iis manager. select site.
2)select the output caching feature from the middle pane.
3)select edit feature setting from the middle pane.
4)check the enable cache and enable kernel cache box and click ok.
if you want to set the ETag as blank you could also do by adding below code in web.config file:
<httpProtocol>
<customHeaders>
<add name="ETag" value="" />
</customHeaders>
</httpProtocol>
refer this below article for more detail:
Caching
To use or not to use ETag, that is the question.
Configure IIS Output Caching
I've read that IIS after version 7 automatically enables E-tags, however, I ran a Pingdom speed test and the report advised me to enable E-tags. I'm not sure that report is accurate, or the information I read about IIS 7 and newer may not be correct.

Unable to host large files on IIS webserver

I'm running IIS 8 on Windows Server 2012R2, and I'm having an issue. I'd like to be able to host large files, but it's causing problems. If I put anything over ~400MB on it, then when I try to access that file from a browser I get a "404 file not found" error.
I should note that smaller files work fine. Any thoughts?
The problem could be that your MIME types need to be modified. From https://serverfault.com/a/78526/12894:
What is probably happening is that your server doesn't know that .war
is a type of file that needs to be downloaded rather than executed. It
then is run through your allowed Web Service Extensions for any
matches. If it doesn't find one, it throws a 404 error even though the
file does in fact exist.
If you set a MIME type for war files of type application/octet-stream,
that should resolve your issue.
See also the Microsoft article Requests for static files return 404 error (IIS 6.0)
Have you tried looking at the Web.config file for the maxrequestlength tag? The problem in this case is not the upload, but rather the request for the file, when the page is loaded. Look for the following line:
<httpruntime maxrequestlength="51200" executiontimeout="7200"/>
Where I set the second number to 2 hours (just a random timeout time) and the first number is the maximum file size that a page that needs the file can request. In this case, you can have 500Mb of upload size. This may fix it, however, there's also another section that you can edit, added in for security purposes:
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="524288000"/>
</requestFiltering>
</security>
Here, again you have 1024x1024*500=500Mb. This is edited in the session properties - you can do that through the Management Interface or through writing your own scripts. Have a look at MSDN here:
http://technet.microsoft.com/en-us/library/cc725820(v=ws.10).aspx

Write requests to log file in IIS

I have a cabinet which consists of several servers, handling quite a bit of traffic.
I need to construct a system to keep statistics - and I struggle to find out if it's possible or makes sense to make a null-request to a server? That is, calling something like http://XXX.XXX.XXX.XXX?objectid=9563828&sreq=2854&nc=29291947829 and letting IIS do nothing with it, except adding the request in the log.
As mentioned, my servers handle a lot of traffic - and every bit of CPU-power and byte I can save, counts in the long run = save money.
At the moment, my plan is to make IIS return nothing on 404-errors, but I'm not sure if this is the best approach. And are all requests logged (having caching in mind)?
Theories or suggestions, please?
Solved - it is possible by adding
<configuration>
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
in the configuration file. The reason I didn't succeed, is that this command is apparently only supported from IIS 7.0 and later and I was testing it on a version 6.5

How do I prevent default IIS compression on a response that is already compressed?

TLDR
I have an IHttpHandler that performs compression. It works fine on its own. But then I added an IHttpModule that performs a completely unrelated task on those (and all other) responses, and now IIS is re-compressing the already-compressed responses. How can I prevent this?
The Whole Story
I have an IHttpHandler implementation that performs combination and compression (among other things) for CSS and JS files. Everything in the IHttpHandler works exactly like I want it to.
But then I added an IHttpModule implementation that removes unnecessary response headers (Server, X-AspNet-Version, etc.) from all responses (including the dynamic responses that are generated by the IHttpHandler) during the PreSendRequestHeaders event.
However, it seems that simply registering an IHttpModule, regardless of what it actually does, causes IIS to apply compression to the response, even if the response is already compressed.
So, my IHttpHandler explicitly compresses the response and sets the Content-Encoding header, then (if and only if) the IHttpModule is also registered, IIS re-compresses the response (so there's a doubly-compressed response that browsers can't read).
I don't want to disable all default compression. I still want HTML from views to be compressed (and I want any CSS and JS that doesn't go through the IHttpHandler to also be default-compressed).
I'm guessing there's no easy solution to my problem because it seems like a bug in IIS. IIS should not compress a response that is already compressed.
I tried adding the following to my web.config, but it had no effect:
<httpCompression>
<dynamicTypes>
<add mimeType="text/css" enabled="false" />
<add mimeType="application/javascript" enabled="false" />
</dynamicTypes>
</httpCompression>
(From my interpretation of the documentation, that should disable compression for dynamically generated CSS and JS.)
I also tried this, to no effect:
<httpCompression>
<dynamicTypes>
<clear/>
</dynamicTypes>
<staticTypes>
<clear/>
</staticTypes>
</httpCompression>
(From my interpretation of the documentation, that should disable all default compression.)
Update
In my IHttpHandler, I call context.Response.Flush at the very end. If I remove this call, the response doesn't get double-compressed. I'm fine with this as a solution. Can anyone explain why this is happening?
Update 2
My best guess is that calling Flush puts the response into such a state that IIS doesn't think the response is already compressed (and so it applies default compression). Even though in my module I can check both...
that Response.Headers contains a Content-Encoding header and
that Response.Filter is non-null and is one of the System.IO.Compression types.
Not sure why IIS can't determine that the response is already compressed from those facts.

IIS7.5 OutputCacheModule kernel caching 'public' ignoring URL

Have some strange behaviour regarding output caching in an ASP.NET 4 application on IIS 7.5. I've been able to repeat the problem simply on other empty setups, I'm certain this is a bug, but unsure how to report it to Microsoft.
A site in IIS responds to more than 1 domain, the .NET application examins the hostname, and produces content accordingly. For example, it may print the name of the request URL in a blank page. Eg, www.first-domain.com, and www.second-domain.com
The web.config has the appropriate caching, urlCompression, and httpCompression all turned OFF under the system.webServer node.
The aspx page sets the cache-control header for public, with either a future date for expires, or a max-age value.
Visiting www.first-domain.com outputs the page that successfully writes 'www.first-domain.com'.
However, visiting www.second-domain.com outputs a page that writes 'www.first-domain.com'.
Examining the failed-request-traces, System.Web.Caching.OutputCacheModule has found the cached output (even though the .config files have turned the function off), the cache has matched even though the request URL hostname are different, and thus the second request will output the results of the first request to the different domain for as long as the max-age/expiry was set for, before the correct page for the second-domain will appear.
Either setting cache-control to private, or removing the 'OutputCache' module in the web.config solves the problem, while maintaining the correct cache-control headers sent to the browser, but obviously, I can't take advantage of kernel caching when I need it.
I can't find any MSDN documentation on how the OutputCacheModule is configured.
Has anyone else experienced this issue, how can I go about enabling kernel caching and let it take into account URL Hostname (without separating the application to different sites in IIS).
Thanks.
Update:
Adding SetSlidingExpiration has no effect, as the kernal cache still caches the output regardless of the request hostname. The only scenario now is to either disable output caching, or run a duplicate instance of the app on each domain it will run - considering the drop in server performance this would result in vs. the increase of performance gained in using output caching, we decided to disable output caching for this app.
No answer has been provided after 9 months, and no solution has been found, only a workaround, perhaps this will be fixed in the next version of IIS greater than 7.5...
--
Adding SetSlidingExpiration has no effect, as the kernal cache still caches the output regardless of the request hostname. The only scenario now is to either disable output caching, or run a duplicate instance of the app on each domain it will run - considering the drop in server performance this would result in vs. the increase of performance gained in using output caching, we decided to disable output caching for this app.
I was having a very similar problem and no solutions here helped me.
TLDR: Forcefully removing the OutputCache module on the Web.config was the only solution I found.
My scenario was a little bit different.
I have CORS set up in Application_BeginRequest, answering Access-Control-Allow-Origin for specific hosts that call me (setting it to * has not been reliable).
My Controller also sets Cache-control: public for it's responses.
What I found
Whenever I set Cache-control: public, IIS forcefully caches the response. Breakpoints on either Application_BeginRequest or my Controller were never hit a second time.
Disabling output and kernel caching via IIS Manager as seen below would have me hitting the Application_BeginRequest breakpoints, but never got me into the Controller. Something was still caching responses.
This article suggested removing the OutputCache module from IIS would help.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="OutputCache" />
</modules>
</system.webServer>
Doing so allowed me to hit my Controller, finally.
What would help even more
If someone from MS or not could shine a light whether there is a way to change this behavior. OutputCache could be useful in some parts of an application and unnecessary in others.
Beware
Maybe I'm(we're?) solving the wrong problem here.
Maybe IIS was taking over caching in this scenario because it should. Maybe proxies along the way between my server and the user would behave just like that in that exact scenario, and if that's the case then working around this on IIS is wrong. I'll have to figure that out and maybe you should too.
I have similar problem. I use custom url rewriter. I have pages example.com/articles and example.com/art-ANY_ID.html. Both url map to articles.aspx (in second example as articles.aspx?id=ANY_ID). It worked fine with ASP.NET 2.0 and Classic pipeline mode. After we have changed it to ASP.NET 4 and integrated mode, we have got strange behaviour: both url return identically output. It was any page like example.com/art-ANY_ID.html.
Now we removed <add extension=".html" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" /> from section <caching enabled="true" enableKernelCache="true"> and it fine works. I not understand why http.sys cache it.
Have you find any explanations?

Resources