1

Hi I need some help with configuring our IIS (8.0) to allow images to be delivered from the image folder and all its subfolders.

Our web.config is located in the root. We then serve most files from the dist folder. Images are located in ./dist/img/* . There are several image folder.

This is our configuration I think its primarily the handlers section that is interesting.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <tracing>
            <traceFailedRequests>
                <remove path="*" />
                <add path="*">
                    <traceAreas>
                        <add provider="ASP" verbosity="Verbose" />
                        <add provider="ASPNET" areas="Infrastructure,Module,Page,AppServices" verbosity="Verbose" />
                        <add provider="ISAPI Extension" verbosity="Verbose" />
                        <add provider="WWW Server" areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module,FastCGI" verbosity="Verbose" />
                    </traceAreas>
                    <failureDefinitions statusCodes="200-999" />
                </add>
            </traceFailedRequests>
        </tracing>
        <rewrite>
            <rules>
                <!-- Redirect root url to index -->
                <rule name="Default route" stopProcessing="true">
                    <match url="^$" />
                    <action type="Rewrite" url="/dist/index.html" />
                </rule>
                <!-- Remove dist folder in URL -->
                <rule name="Add dist folder" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{PATH_INFO}" pattern="^/dist/" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/dist/{R:0}" />
                </rule>
            </rules>
            <outboundRules>
                <rule name="Remove ETag">
                    <match serverVariable="RESPONSE_ETag" pattern=".+" />
                    <action type="Rewrite" value="" />
                </rule>
            </outboundRules>
        </rewrite>
        <handlers>
            <clear />
            <!-- Serve files in dist folder as static content -->
            <add name="ImgStaticContent"
                 path="/dist/img/*"
                 verb="*"
                 allowPathInfo="true"
                 type="System.Web.StaticFileHandler"
            />
            <add name="ModelsStaticContent"
                 path="/dist/models/*"
                 verb="*"
                 allowPathInfo="true"
                 type="System.Web.StaticFileHandler"
            />
            <add name="DistStaticContent"
                 path="/dist/*"
                 verb="*"
                 allowPathInfo="true"
                 type="System.Web.StaticFileHandler"
            />
        </handlers>

        <!-- Cache static content  -->
        <staticContent>
            <!-- Remove ETAG IN IIS >= 8 ; for IIS 7/7.5 see the Rewrite rules (bigger description of why you might remove etag down there aswell)
            <clientCache setEtag="false"/>
            -->
            <!-- Set expire headers to 30 days for static content-->
            <clientCache cacheControlMaxAge="30.00:00:00" cacheControlMode="UseMaxAge"/>
            <!-- use utf-8 encoding for anything served text/plain or text/html -->
            <!-- in the case of .html files; if you AJAX load html files (i.e. in angular) then remove these two lines. -->
            <remove fileExtension=".html"/>
            <mimeMap fileExtension=".html" mimeType="text/html; charset=UTF-8"/>
            <remove fileExtension=".css"/>
            <mimeMap fileExtension=".css" mimeType="text/css"/>
            <remove fileExtension=".js"/>
            <mimeMap fileExtension=".js" mimeType="text/javascript"/>
            <remove fileExtension=".json"/>
            <mimeMap fileExtension=".json" mimeType="application/json"/>
            <remove fileExtension=".rss"/>
            <mimeMap fileExtension=".rss" mimeType="application/rss+xml; charset=UTF-8"/>
            <remove fileExtension=".xml"/>
            <mimeMap fileExtension=".xml" mimeType="application/xml; charset=UTF-8"/>
            <!-- HTML5 Audio/Video mime types-->
            <remove fileExtension=".mp3"/>
            <mimeMap fileExtension=".mp3" mimeType="audio/mpeg"/>
            <remove fileExtension=".mp4"/>
            <mimeMap fileExtension=".mp4" mimeType="video/mp4"/>
            <remove fileExtension=".ogg"/>
            <mimeMap fileExtension=".ogg" mimeType="audio/ogg"/>
            <remove fileExtension=".ogv"/>
            <mimeMap fileExtension=".ogv" mimeType="video/ogg"/>
            <remove fileExtension=".webm"/>
            <mimeMap fileExtension=".webm" mimeType="video/webm"/>
            <!-- Proper svg serving. Required for svg webfonts on iPad -->
            <remove fileExtension=".svg"/>
            <mimeMap fileExtension=".svg" mimeType="image/svg+xml"/>
            <remove fileExtension=".svgz"/>
            <mimeMap fileExtension=".svgz" mimeType="image/svg+xml"/>
            <!-- HTML4 Web font mime types -->
            <!-- Remove default IIS mime type for .eot which is application/octet-stream -->
            <remove fileExtension=".eot"/>
            <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject"/>
            <remove fileExtension=".ttf"/>
            <mimeMap fileExtension=".ttf" mimeType="application/x-font-ttf"/>
            <remove fileExtension=".ttc"/>
            <mimeMap fileExtension=".ttc" mimeType="application/x-font-ttf"/>
            <remove fileExtension=".otf"/>
            <mimeMap fileExtension=".otf" mimeType="font/opentype"/>
            <remove fileExtension=".woff"/>
            <mimeMap fileExtension=".woff" mimeType="application/font-woff"/>
            <remove fileExtension=".woff2"/>
            <mimeMap fileExtension=".woff2" mimeType="font/woff2"/>
            <remove fileExtension=".crx"/>
            <mimeMap fileExtension=".crx" mimeType="application/x-chrome-extension"/>
            <remove fileExtension=".xpi"/>
            <mimeMap fileExtension=".xpi" mimeType="application/x-xpinstall"/>
            <remove fileExtension=".safariextz"/>
            <mimeMap fileExtension=".safariextz" mimeType="application/octet-stream"/>
            <!-- Flash Video mime types-->
            <remove fileExtension=".flv"/>
            <mimeMap fileExtension=".flv" mimeType="video/x-flv"/>
            <remove fileExtension=".f4v"/>
            <mimeMap fileExtension=".f4v" mimeType="video/mp4"/>
            <!-- Assorted types -->
            <remove fileExtension=".ico"/>
            <mimeMap fileExtension=".ico" mimeType="image/x-icon"/>
            <remove fileExtension=".webp"/>
            <mimeMap fileExtension=".webp" mimeType="image/webp"/>
            <remove fileExtension=".htc"/>
            <mimeMap fileExtension=".htc" mimeType="text/x-component"/>
            <remove fileExtension=".vcf"/>
            <mimeMap fileExtension=".vcf" mimeType="text/x-vcard"/>
            <remove fileExtension=".torrent"/>
            <mimeMap fileExtension=".torrent" mimeType="application/x-bittorrent"/>
            <remove fileExtension=".cur"/>
            <mimeMap fileExtension=".cur" mimeType="image/x-icon"/>
            <remove fileExtension=".webapp"/>
            <mimeMap fileExtension=".webapp" mimeType="application/x-web-app-manifest+json; charset=UTF-8"/>
        </staticContent>
        <urlCompression doStaticCompression="true" doDynamicCompression="true" />
        <httpCompression minFileSizeForComp="0">
            <dynamicTypes>
                <clear />
                <add enabled="true" mimeType="text/*"/>
                <add enabled="true" mimeType="message/*"/>
                <add enabled="true" mimeType="application/x-javascript"/>
                <add enabled="true" mimeType="application/javascript"/>
                <add enabled="true" mimeType="application/json"/>
                <add enabled="false" mimeType="*/*"/>
                <add enabled="true" mimeType="application/atom+xml"/>
                <add enabled="true" mimeType="application/atom+xml;charset=utf-8"/>
            </dynamicTypes>
            <staticTypes>
                <clear />
                <add enabled="true" mimeType="text/*"/>
                <add enabled="true" mimeType="message/*"/>
                <add enabled="true" mimeType="application/javascript"/>
                <add enabled="true" mimeType="application/atom+xml"/>
                <add enabled="true" mimeType="application/xaml+xml"/>
                <add enabled="true" mimeType="application/json"/>
                <add enabled="false" mimeType="*/*"/>
            </staticTypes>
        </httpCompression>
        <directoryBrowse enabled="false"/>
        <validation validateIntegratedModeConfiguration="false"/>
    </system.webServer>
</configuration>

The problem we have is that files are not delivered correctly. I get a 404 when asking for any images apart from the ones directly below the image folder.

UPDATE

Here is what the error report looks like for the IIS. (404) The correct handler is used and the image has been validated to be in the Physical path given in the error report.

Detailed Error Information:
Module     ManagedPipelineHandler
Notification       ExecuteRequestHandler
Handler    ImgStaticContent
Error Code     0x00000000
Requested URL      host:80/dist/img/signs/traffic_signs/forbuds_marken/c31-11.png
Physical Path      D:\home\site\wwwroot\dist\img\signs\traffic_signs\forbuds_marken\c31-11.png
Logon Method       Anonymous
Logon User     Anonymous

Update

If I add a handler for a specific subfolder like below. Those images are delivered correctly. Given the number of subfolders this is not possible to do for all folders though.

        <add name="test"
             path="/dist/img/signs/traffic_signs/forbuds_marken/*"
             verb="*"
             allowPathInfo="true"
             type="System.Web.StaticFileHandler" />

How do I configure handlers to work on subdirs and not just main directories.

  • 1
    Sounds like you haven't correctly setup server folder and file permissions... – Simon Hayter Nov 7 '17 at 14:17
  • It might have something to do with that. I am running on azure web services and I have seen that the group permissions and permissions are undefined. It also seems the user is running as undefined. – Pablo Jomer Nov 7 '17 at 14:26
  • Not sure that article helps though as these things are setup already by azure on default. – Pablo Jomer Nov 7 '17 at 14:27
  • Depends on how you 'create' those folders or files. – Simon Hayter Nov 7 '17 at 16:37
  • Wildcard works properly if I don't include the folder path but rather list by file type instead. Not sure why it works like this. – Pablo Jomer Nov 8 '17 at 17:02
1

Items I would recommend verifying:

  • Check your permissions (user and group) on both your image folders and files.
  • Check the ownership on your web directory trees.
  • You mentioned the config is in the root, verify the web owner has the appropriate access to that config.

Once you've checked and if necessary corrected those permissions, if you are still getting errors using an error monitoring tool can help you find exceptions/errors more quickly, and perhaps identify the exact location of the problem. There are a number of them including Sentry, Bugsnag and Airbrake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.