IIS 7.5 and images not being cached - iis

I cannot get the image files to cache. I have tried everything that I have found on this site and others and still cannot get them to cache.
Web config setting that I have tried
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
</staticContent>
<httpProtocol allowKeepAlive="true" />
<caching enabled="true" enableKernelCache="true">
<profiles>
<add extension=".png" policy="CacheUntilChange" />
<add extension=".jpg" policy="CacheForTimePeriod" duration="12:00:00" />
</profiles>
</caching>
Here is the response headers for 1 of the images
Key Value
Response HTTP/1.1 200 OK
Cache-Control no-cache
Content-Type image/png
Last-Modified Thu, 16 Dec 2004 18:33:28 GMT
Accept-Ranges bytes
ETag "a1ca4bc9de3c41:0"
Server Microsoft-IIS/7.5
X-Powered-By ASP.NET
Date Fri, 18 May 2012 13:21:21 GMT
Content-Length 775

The following should cause the browsers to cache your images:
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
</staticContent>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="public" />
</customHeaders>
</httpProtocol>
The <caching>...</caching> block is for server-side caching, not client side caching.

In case anyone needs to configure your site as Chrome Audits or GTMetrix require I've configured my environments with the following (thanks to Marco's answer):
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="365.00:00:00" />
using 365 days and both tools took that value as acceptable for a cache time.

Related

Cache-control headers not added on azure linux app service

I host an angular frontend inside an Azure App Service on Linux. Stack is Node 12.
In order to enable the response headers "Cache-Control" for the static files I have added the line
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="3.00:00:00" />
inside the Web.config file as suggested in the microsoft documentation here
The Web.config file looks like this:
<configuration>
<system.webServer>
<handlers>
<clear />
<add
name="StaticFile"
path="*" verb="*"
modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule"
resourceType="Either"
requireAccess="Read" />
</handlers>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
<mimeMap fileExtension=".*" mimeType="application/octet-stream" />
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="3.00:00:00" />
</staticContent>
<rewrite>
<rules>
<rule name="redirect all requests" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
</conditions>
<action type="Rewrite" url="index.html" appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
Unfortunately the headers are not set correctly. Is there something wrong with the Web.config file? Does the Azure App Service on Linux have to do something with it?
The web.config file is only for IIS configuration system, but IIS is not for Linux.
So you could not set the cache-control header in web.config file.
If you have entity instance for Linux, you could use Apache .htaccess file:
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
If you don't have entity instance for Linux, you could set the header in code:
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setHeader("Expires", "0"); // Proxies.
I have tried using .htaccess file on Azure, but it did not work as Azure is a PaaS, which did not include a entity instance.

IIS:Set and serve both gzip and brotli compression conditionally

I want to server some static contents to browser and found that Brotli reduces the size of final download package by 43% compare to gzip.
I first tried by setting up only Brotli and all modern browser download the compressed file. But when tried with IE11 (which doesn't support brotli), download original contents without any compression which impact performance.
To handle this, I kept both Gzip and Brotli on IIS. But now all browser downloads the contents only in Gzip format most probably because of the request header order where gzip comes first.
I want to make it conditional so that by default browser download the contents in Brotli format and if browser doesn't support it then switch to gzip format automatically.
Any idea how to do it?
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<scheme name="br" dll="%Windir%\system32\inetsrv\brotli.dll" dynamicCompressionLevel="5" staticCompressionLevel="11" />
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="application/atom+xml" enabled="true" />
<add mimeType="application/xaml+xml" enabled="true" />
<add mimeType="image/svg+xml" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
You can enable multiple compression schemes both Brotli and Gzip compression and set the compression scheme prioritization.
IIS ships a default compression scheme provider gzip, it is registered as the gzip scheme in applicationHost.config by default. But if you also want use the Brotli compression, you need to add iisbrotli.dll as the Brotli compression scheme provider in applicationHost.config. Add Brotli compression scheme
Regarding how to set Compression Scheme Prioritization, it is divided into two versions: IIS 10.0 Version 1803 or Above and Before IIS 10.0 Version 1803.
About IIS 10.0 Version 1803 or Above, the priority of each compression scheme is determined by its order in the collection of the element.
About before IIS 10.0 Version 1803, it prioritizes the compression scheme based on the scheme order appearing in the Accept-Encoding request header value, but IIS always prioritizes gzip over br for the typical scenario that the browser sets Accept-Encoding: gzip, deflate, br header in the request. A possible workaround is installing the URL Rewrite Module and configuring a rewrite rule to modify the Accept-Encoding header value.
Enabling Multiple Compression Schemes

Gzip compression on IIS - Can't get it to work

I have an existing IIS application, and I am trying to get GZIP server side compression to work. The application runs on EPIServer CMS (which I am not that familiar with) - Thinking this could be related to the CMS somehow, as a first step...
I decided to create a new IIS application and this time using Umbraco (another CMS that I am very familiar with) - I have created a basic page with some CSS files and images,
Content-Encoding: gzip
header.
This is what I have tried and checked.
Working locally, I am running windows 10. and IIS 10
I have enabled Dyamic Content Compression and Static Content Compression under Internet Information Services > Performance Features in Windows Features
For the locally set up website in IIS I have ensured that the compression section has both Enable Dynamic & Static check boxes are ticked.
In my web-config file I have added this single line
<urlCompression doDynamicCompression="true" doStaticCompression="true" dynamicCompressionBeforeCache="false" />
When the Webconfig has this line I inspect the headers in my browser:
REQUEST HEADERS
Accept: text/css,*/*;q=0.1
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Host: umbracotest.site
Proxy-Connection: keep-alive
Referer: http://umbracotest.site/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36
RESPONSE HEADERS
Accept-Ranges: bytes
Content-Type: text/css
Date: Tue, 01 May 2018 15:09:02 GMT
ETag: "03739d0e978d31:0"
Last-Modified: Tue, 19 Dec 2017 16:52:54 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding
If I change that webconfig line slightly - dynamicCompressionBeforeCache="false" to true - then I just get a whole bunch of symbols in the browser - does that mean anything?
If I add a few more lines in to my webconfig to look like this:
<system.webServer>
<httpCompression>
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="image/jpeg" enabled="true" />
<add mimeType="image/png" enabled="true" />
<add mimeType="image/svg" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
<dynamicTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="application/x-javascript" enabled="true" />
<add mimeType="image/jpeg" enabled="true" />
<add mimeType="*/*" enabled="false" />
</dynamicTypes>
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"
dynamicCompressionLevel="8" />
</httpCompression>
<urlCompression doDynamicCompression="true" doStaticCompression="true"
dynamicCompressionBeforeCache="false" />
headers are still the same.
C:\inetpub\temp\IIS Temporary Compressed Files\MYAPPPOOL-NAME << this folder is created but empty.
This is a ASP.net MVC application
Any ideas?
So after banging my head on the wall for about 8 hours, I finally got it to work!
After checking everything twice, reading every post I could find on the topic, I came across a comment to a similar question that suggested it could be something to do with my antivirus software. I'm working in an enterprise environment and I don't have the rights to disable it on my local machine. So I deployed the code to our staging server......... and it works.
So in case someone else has this problem, try and disable your anti-virus and see if that makes any difference, it worked for me.

Remove cache HTTP response headers from Web Api in Azure

I am trying to remove unwanted Cache-Control, Pragma and Expires HTTP headers in responses from a Web Api 2 project hosted on an Azure website in Standard mode.
I have tried the following in Global.asax Application_PreSendRequestHeaders:
var headers = ((HttpApplication)sender).Context.Response.Headers;
headers.Remove("Cache-Control");
headers.Remove("Pragma");
headers.Remove("Expires");
This works when debugging in Visual Studio. But on Azure, the headers are only removed for GET requests and not HEAD or POST requests.
Grateful for any suggestions!
Azure Web Sites supports the request filtering module, so you can do this in your web.config:
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Cache-Control" />
<remove name="Pragma" />
<remove name="Expires" />
</customHeaders>
</httpProtocol>
</system.webServer>
Disclaimer: I am not condoning the removal of these headers, which are an essential part of the HTTP protocol.
Removing cache headers says to clients "it is entirely up to you to decide how to cache this response", which may result in odd and hard-to-reproduce errors in production. If you want to disable caching, you should set these headers to values which explicitly disable caching:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>

Why does ServiceStack return 404 with this configuration?

I have the following configuration.
<location path="services">
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
</location>
If I add another <system.webServer /> section, not within a location element, ServiceStack returns 404 for all requests. Remove it, and everything works again.
Here's an example response:
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/7.5
X-Powered-By: ServiceStack/3.926 Win32NT/.NET
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 19 Nov 2012 23:15:46 GMT
Content-Length: 1528
Handler for Request not found:
Request.ApplicationPath: /MyWebApp.Web.UI
Request.CurrentExecutionFilePath: /MyWebApp.Web.UI/services/echo/
Request.FilePath: /MyWebApp.Web.UI/services/echo/
Request.HttpMethod: GET
Request.MapPath('~'): D:\Lib\MyWebApp\2013\MyWebApp\MyWebApp.Web.UI
Request.Path: /MyWebApp.Web.UI/services/echo/
Request.PathInfo:
Request.ResolvedPathInfo: /services/echo
Request.PhysicalPath: D:\Lib\MyWebApp\2013\MyWebApp\MyWebApp.Web.UI\services\echo\
Request.PhysicalApplicationPath: D:\Lib\MyWebApp\2013\MyWebApp\MyWebApp.Web.UI\
Request.QueryString:
Request.RawUrl: /MyWebApp.Web.UI/services/echo/
Request.Url.AbsoluteUri: http://localhost/MyWebApp.Web.UI/services/echo/
Request.Url.AbsolutePath: /MyWebApp.Web.UI/services/echo/
Request.Url.Fragment:
Request.Url.Host: localhost
Request.Url.LocalPath: /MyWebApp.Web.UI/services/echo/
Request.Url.Port: 80
Request.Url.Query:
Request.Url.Scheme: http
Request.Url.Segments: System.String[]
App.IsIntegratedPipeline: True
App.WebHostPhysicalPath: D:\Lib\MyWebApp\2013\MyWebApp\MyWebApp.Web.UI
App.WebHostRootFileNames: [global.asax,global.asax.cs,header.html,list.html,login.html,MyWebApp.web.ui.csproj,MyWebApp.web.ui.csproj.user,packages.config,web.config,bin,humanresources,js,obj,properties,styles,_sgbak]
App.DefaultHandler: DefaultHttpHandler
App.DebugLastHandlerArgs: GET|/MyWebApp.Web.UI/services/echo/|D:\Lib\MyWebApp\2013\MyWebApp\MyWebApp.Web.UI\services\echo\
Is it not possible to have another system.webServer section? I'd like to add IIS url rewriting rules there.
The extra system.webServer declaration might be interfering with ServiceStack's auto-inferencing of the hosted path from your Web.Config.
You can try to set the path manually to see if that helps, e.g in your AppHost.Configure():
SetConfig(new HostConfig {
HandlerFactoryPath = "services",
});

Resources