none
[Node.js][Web Apps] Output cache not working for node web app RRS feed

  • Question

  • I am using git to deploy an express.js app as a web app in azure and it is working fine except that I cannot seem to figure out how to get caching profiles to work.

    The application dynamically serves requests such as /api/images/myimage.png and I was hoping by adding the "caching" section below for certain extensions it would cause images served in this way to be cached.

    That does not however seem to be happening - have I missed something obvious? My understanding is that output caching should work with IISNode fine.

    <?xml version="1.0" encoding="utf-8"?>
    <!--
         This configuration file is required if iisnode is used to run node processes behind
         IIS or IIS Express.  For more information, visit:
    
         https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
    -->
    <!-- https://mediocre.com/forum/topics/one-does-not-simply-run-node-js-on-microsoft-azure
    https://azure.microsoft.com/en-gb/documentation/articles/nodejs-specify-node-version-azure-apps/
    https://tomasz.janczuk.org/2012/09/selecting-nodejs-version-in-windows.html
    https://github.com/tjanczuk/iisnode/wiki/iisnode-releases -->
    
    
    <configuration>
      <system.webServer>
          <httpProtocol>
             <customHeaders>
                <add name="X-Web-Config" value="MyCustomValue" />
             </customHeaders>
          </httpProtocol>
        <!-- custom caching so that images are cached efficiently rather than pulled from backend every time -->
        <caching enabled="true" enableKernelCache="true" maxCacheSize="1000" maxResponseSize="5120000">
          <profiles>
            <add extension=".jpg" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="24:00:00" />
            <add extension=".png" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="24:00:00" />
            <add extension=".gif" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="24:00:00" />
            <add extension=".css" policy="CacheForTimePeriod" kernelCachePolicy="CacheForTimePeriod" duration="1:00:00" />
          </profiles>
        </caching>
        <!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
        <webSocket enabled="false" />
        <handlers>
          <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
          <add name="iisnode" path="bin/www" verb="*" modules="iisnode"/>
        </handlers>
        <rewrite>
          <rules>
            <!-- Do not interfere with requests for node-inspector debugging -->
            <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
              <match url="^bin/www\/debug[\/]?" />
            </rule>
    
            <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
            <rule name="StaticContent">
              <action type="Rewrite" url="public{REQUEST_URI}"/>
            </rule>
    
            <!-- All other URLs are mapped to the node.js site entry point -->
            <rule name="DynamicContent">
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
              </conditions>
              <action type="Rewrite" url="bin/www"/>
            </rule>
          </rules>
        </rewrite>
        
        <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
        <security>
          <requestFiltering>
            <hiddenSegments>
              <remove segment="bin"/>
            </hiddenSegments>
          </requestFiltering>
        </security>
    
        <!-- Make sure error responses are left untouched -->
        <httpErrors existingResponse="PassThrough" />
    
        <!--
          You can control how Node is hosted within IIS using the following options:
            * watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
            * node_env: will be propagated to node as NODE_ENV environment variable
            * debuggingEnabled - controls whether the built-in debugger is enabled
    
          See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
        -->
        <!--<iisnode watchedFiles="web.config;*.js"/>-->
      </system.webServer>
    </configuration>




    Monday, April 11, 2016 4:13 PM

Answers

  • The answer is that the rewrite needs to point to something with an appropriate extension, e.g. www.js instead of www. This is because the extension under the <profiles> section under <caching> is matched against the redirected url, not the original url of the incoming request. 
    • Marked as answer by WillFG99 Friday, April 15, 2016 2:32 PM
    Friday, April 15, 2016 2:32 PM

All replies

  • To cache static contents, you can try to use staticContent section, e.g.

    <staticContent>
        <clientCache cacheControlMaxAge="7.00:00:00" cacheControlMode="UseMaxAge" />
    </staticContent>

    And I have a several test about requesting image from Expressjs application on Azure with the web.config in different configurations using caching-profiles and staticContent section.

    • caching-profiles

    • staticContent

    And according the description of Caching <caching>:

    Output caching works best with pages that are semi-dynamic, such as an ASP.NET page that is dependent on a database table that does not change often.
    Output caching is unnecessary for static files, such as HTML, JPG, or GIF files, and can cause more memory overhead for dynamic ASP.NET or PHP pages that read from a database that changes frequently.

    If I do not misunderstand it, please try to use <staticContent> section.

    Any concern, please free feel to let me know.

    Tuesday, April 12, 2016 2:55 AM
    Moderator
  • Thanks Gary,

    Does the above work when the content *isn't* static?

    I'm using a route in express to serve the content and not express.static. This is because I have to call an API to pull the data from somewhere else.

    What I might try is to see if it works caching .js files as I'm not sure whether IISNode identifies the extension of the "script" that is hit (i.e. .js in this case) or the extension of the request URL (e.g. /api/images/something.png).

    Will

    Tuesday, April 12, 2016 8:29 AM
  • I've been doing some more investigating on a VM rather than in Azure.

    It seems that iisnode was restarting the node.exe process after each set of requests as logging was enabled. I would have expected iisnode / iis to ignore these text files being generated under bin/www but this didn't seem to be the case, causing a restart of node.exe. This meant that nothing was cached.

    Having stopped iisnode from logging it is now caching files from /public but not from anywhere else.

    This can be diagnosed using netsh http show cachestate.

    It is still not caching the output of my API but this is going in the right direction.

    Thursday, April 14, 2016 3:47 PM
  • The answer is that the rewrite needs to point to something with an appropriate extension, e.g. www.js instead of www. This is because the extension under the <profiles> section under <caching> is matched against the redirected url, not the original url of the incoming request. 
    • Marked as answer by WillFG99 Friday, April 15, 2016 2:32 PM
    Friday, April 15, 2016 2:32 PM