How to Use HTTP Detailed Errors in IIS7

Published on December 12, 2007 by

Updated on December 12, 2007 by IIS Team

Average Rating  Rate It (1)

RSS

Introduction

Every Web-Site Administrator or Web Developer has seen "404 - File not found" , "401 - Unauthorized" or "500 - Server Error" messages in his browser. This article will help you understand how and why IIS generates these errors and how they can be configured.

You might think that generating error messages doesn't seem to justify a full blown article. But there is more to errors than meets the eye. Error messages are a touchy topic, because every error reveals more about your web-site than you might want. And the more information somebody can gather about your site the likelier it is that you get hacked. Just search for "google hacking" or "cross-site scripting" and you will find a wealth of information on this topic.

But error messages are also a valuable tool to troubleshoot problems. Developers and Web-Site Administrators want as much detail as possible when an error occurs. Ideally the error message would already give recommendations on how to fix the problem. Here is how IIS7 addresses these fundamentally opposed goals.

Errors, What Errors?

This paper talks about HTTP errors as specified in the HTTP RFC (RFC 2616 - section 6.1.1).  A HTTP error is always expressed by sending a response with a status code greater than 400 back to the requesting client.

Client errors

Status codes between 400 and 500 specify an error made by the client, e.g. bad syntax or a request to a resource that doesn't exist. You can try this by requesting a bogus URL from the web-site of your choice, for example: http://<IIS7Server>/this_resource_does_not_exist.  You get a "404 - File not found" error.

Server errors

Status codes starting with 500 are errors caused by the server. The most common causes for 500 errors on IIS systems are

  • an ASP or ASPX page that contains a syntax error
  • the web server configuration or the application configuration cannot be read or is invalid
  • the site is stopped

It is important to notice that browsers like IE often replace errors returned from a web server with their own. This sometimes makes troubleshooting harder. In Internet Explorer you can turn this off. Go to the "Tools" menu, select "Internet Options", click the "Advanced" tab and find the "Show friendly HTTP error messages" check box and uncheck it. If you want to see the raw response you have to use HTTP tools like WFETCH in the IIS 6.0 Resource Kit (see "Related Links").

HTTP Errors in IIS 7

There are two things that can happen when the httpError module (custerr.dll) encounters an error.

  1. A custom error is generated
  2. a detailed error is generated

Custom errors are error pages that the regular users of your web-site will see. They contain a brief error description why the error happened, but nothing else. Here is the custom error generated when you request a resource that does not exist, for example http://<IIS7Server>/this_resource_does_not_exist

 

Detailed errors are intended for local administrators and developers. They are supposed to give a wealth of information that can help to immediately fix the problem. Here is an example of the same request, but now returning a Detailed Error:

 

This is dangerous of course, because Detailed Errors contain information about the inner workings of your web-site. Only trusted personal should see a Detailed Error. The only way to ensures this is to only generate a detailed error if the request comes from the local machine. As soon as the request is not local a custom error is generated. Let's have a look at the following flow diagram: 

 

 

Data Flow

First: Error check

The httpError module receives a notification if a response is about to be sent (RQ_SEND_RESPONSE notification). The httpError module checks the status code of this response and immediately returns if the status code is not greater than 400.

Second: Custom Error or Detailed Error

The next check is determined by the request origin (is the request a local request or does it come from remote) and the setting of the overrideMode property. The overrideMode is set to remoteOnly which means that Custom Errors are generated for every remote request. If overrideMode is set to on then all error responses will become Custom Error. If overrideMode is set to Off all error responses will become Detailed Errors. The following table clarifies this behavior:

overrideMode setting

Request origin

Action

RemoteOnly (default)

Local

Detailed Error

RemoteOnly (default)

Remote

Custom Error

On

Local

Custom Error

On

Remote

Custom Error

Off

Local

Detailed Error

Off

Remote

Detailed Error

 

Note: The overrideMode and its arguments will be renamed to errorMode after Beta2. Here is how the table if you have a post-Beta2 build of Windows Vista.

errorMode

Request origin

Action

detailedLocalOnly (default)

Local

Detailed Error

detailedLocalOnly (default)

Remote

Custom Error

custom

Local

Custom Error

custom

Remote

Custom Error

detailed

Local

Detailed Error

detailed

Remote

Detailed Error

 

  1. If the httpError module determines that a Custom Error needs to be generated it looks into its configuration if a matching error can be found.  If a match is found it send the static file, redirects the request or executes the URL specified. If no match can be found IIS7 send a very basic one-line message containing the status code. The next section explains the Custom Error configuration in detail.
  2. If custerr.dll determines that a Detailed Error needs to be generated another check is needed. IIS7 doesn't touch the response if a module overrode the entity of the response with its own error description. It might contain valuable information. ASP.NET is a good example. The entity of an ASP.NET error response might contain the exception stack and its own error description. A Detailed Error is only generated if the entity body of the response is empty.

<httpErrors> Configuration

Here is the IIS7 custom error section that you get on a clean install:


<httpErrors>
            <error statusCode="401" prefixLanguageFilePath="c:\inetpub\custerr" path="401.htm" />
            <error statusCode="403" prefixLanguageFilePath="c:\inetpub\custerr" path="403.htm" />
            <error statusCode="404" prefixLanguageFilePath="c:\inetpub\custerr" path="404.htm" />
            <error statusCode="405" prefixLanguageFilePath="c:\inetpub\custerr" path="405.htm" />
            <error statusCode="406" prefixLanguageFilePath="c:\inetpub\custerr" path="406.htm" />
            <error statusCode="412" prefixLanguageFilePath="c:\inetpub\custerr" path="412.htm" />
            <error statusCode="500" prefixLanguageFilePath="c:\inetpub\custerr" path="500.htm" />
            <error statusCode="501" prefixLanguageFilePath="c:\inetpub\custerr" path="501.htm" />
            <error statusCode="502" prefixLanguageFilePath="c:\inetpub\custerr" path="502.htm" />
</httpErrors>

 

You see that if the status code of a response is 401, IIS will return a file named 401.htm.

Sub-Status Codes

Many HTTP errors have a sub-status. The IIS7 default Custom Errors configuration doesn't differentiate based sub-status codes. It sends you the same Custom Error page if you enter the wrong credentials (401.1) or if you get access denied based on invalid rights to access a file (401.3). You can see the different sub-status codes in your log files or via Detailed Errors. Here is a list of the different 404 sub-status codes that IIS7 produces.

Status

Description

404.1

Site couldn't be found

404.2

Denied by Policy. The request ISAPI or CGI program is not allowed in the Restriction List.

404.3

The static file handler didn't have the file in its MimeMap and therefore rejected the request.

404.4

No handler was found to serve the request.

404.5

The Request Filtering Module rejected an URL sequence in the request.

404.6

The Request Filtering Module denied the HTTP verb of the request.

404.7

The Request Filtering module rejected the file extension of the request.

404.8

The Request Filtering module rejected a particular URL segment (characters between two slashes).

404.9

IIS rejected to serve a hidden file.

404.10

The Request Filtering module rejected a too long header.

404.11

The Request Filtering module rejected a request that was double escaped.

404.12

The Request Filtering module rejected a request that contained high bit characters.

404.13

The Request Filtering module rejected a request that was too long (request + entity body).

404.14

The Request Filtering module rejected a request with a too long URL.

404.15

The Request Filtering module rejected a request with a too long query string.

 

You can configure the httpErrors section to show a Custom Error for particular sub-status codes. If you add the following line to your httpErrors configuration section IIS7 will return 404_3.htm if a file with a file extension is requested that isn't included in the IIS7 MimeMap (<staticContent> configuration section).


  <error statusCode="404" subStatusCode="3" prefixLanguageFilePath="c:\inetpub\custerr" path="404_3.htm" />

 

How to make the example work:

  1. Add the entry above to your httpErrors configuration section.
  2. Create a file named 404_3.htm in your c:\inetpub\custerr\en-us directory. 
  3. Create a file named test.yyy in you c:\inetpub\wwwroot directory.
  4. Now request http://localhost/test.yyy

The file extension .yyy is not part of the IIS7 MimeMap and the static file handler will not serve it.

New in IIS7: language specific custom errors

Every newer browser includes the language  of the client as a request header. Here an example how this header might look like

Accept-Language: en-us

The syntax and registry of accepted languages is specified in RFC1766.

When generating an error IIS7 takes this header into account when it looks for the custom error file it returns. It generates the path for the custom error using the following logic:

prefixLanguageFilePath configuration setting (for example c:\inetpub\custerr)+
Accept-Language header sent by the client (for example en-us) +
Path configuration setting (for example 404.htm)

Example:

If the browser sends a request for an non-existing resource and the "Accept-Language" header has the value of "en-us" the file that gets returned will be "c:\inetpub\custerr\en-us\404.htm".

If you are from Germany like my poor soul you want your error messages in German. To do this you have to install the Windows Vista Language Pack for German. This will create the c:\inetpub\custerr\de-DE directory with custom error files in it. Now if the browser sends the "Accept-Language" header with the value of "de-DE the file that gets returned will be "c:\inetpub\custerr\de-DE\404.htm".

IIS7 will always fall back to the system language if the directory "de-DE" doesn't exist.

Note: Internet Explorer allows you to configure the Accept-Language header. Go to "Tools" - "Internet Option", select the "General" tab and click the "Languages" button.

Custom Error Options

In the above examples IIS7 sends the contents of the file as the custom error response. IIS7 has two other ways to respond to an error. By executing an URL or by redirecting the request.

ExecuteUrl

If you want to do a bit more in your custom error, e.g. sending an e-mail or logging the error to a database, you can execute an url. This allows you to execute dynamic content like an ASP.NET page. In the example below I replace the 404 custom error. Now IIS7 will execute /404.aspx whenever a 404 error occurs.


<httpErrors>
            <!-- default custom error for 401 errors -->
            <!-- <error statusCode="404" prefixLanguageFilePath="c:\inetpub\custerr" path="404.htm" />-->
          

            <!-- ExecuteURL replaces default file response mode -->
            <error statusCode="404" path=/404.aspx" responseMode="ExecuteURL"/>        

            <error statusCode="403" prefixLanguageFilePath="c:\inetpub\custerr" path="403.htm" />
            <error statusCode="404" prefixLanguageFilePath="c:\inetpub\custerr" path="404.htm" />
            <error statusCode="405" prefixLanguageFilePath="c:\inetpub\custerr" path="405.htm" />
            <error statusCode="406" prefixLanguageFilePath="c:\inetpub\custerr" path="406.htm" />
            <error statusCode="412" prefixLanguageFilePath="c:\inetpub\custerr" path="412.htm" />
            <error statusCode="500" prefixLanguageFilePath="c:\inetpub\custerr" path="500.htm" />
            <error statusCode="501" prefixLanguageFilePath="c:\inetpub\custerr" path="501.htm" />
            <error statusCode="502" prefixLanguageFilePath="c:\inetpub\custerr" path="502.htm" />
</httpErrors>

 

A word of caution: For architectural reasons IIS7 can only execute the URL if it is located in the same Application Pool. Use the redirect feature if you need to execute a Custom Error in a different Application Pool.

IIS7 can also return a 302 Redirect to the browser when a particular error occurs. Redirect is great if you have a web farm for example you can redirect all your errors to a central location that you closely monitor. Here an example:


<section name="httpErrors" type="System.WebServer.Configuration.HttpErrorsSection,

    System.ApplicationHost, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

     overrideModeDefault="Deny" />

 

This is not without risk however. responseMode="File" (which is the default) allows you to specify every file on the disk. This might not work for you if you are very security conscious.

A workable scenario might be to only allow the delegation of the overrideMode (errorMode after Beta2) setting. This enables a developer to receive Detailed Errors for his application even if he is remote. All he has to do is to set overrideMode="Off" (errorMode="detailed" after Beta2). Here is how to configure this scenario:

Allow the delegation of the httpErrors section:


  <section name="httpErrors" type="System.WebServer.Configuration.HttpErrorsSection,

      System.ApplicationHost, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

      overrideModeDefault="Allow" />

 

Second, you can go to the <httpErrors> section in applicationHost.config and change it so that only overrideMode is delegated:


<httpErrors lockAllAttributesExcept="overrideMode" lockElements="error">
            <error statusCode="404" prefixLanguageFilePath="E:\inetpub\custerr" path="404.htm" />
            <error statusCode="401" prefixLanguageFilePath="E:\inetpub\custerr" path="401.htm" />
            <error statusCode="403" prefixLanguageFilePath="E:\inetpub\custerr" path="403.htm" />
            <error statusCode="405" prefixLanguageFilePath="E:\inetpub\custerr" path="405.htm" />
            <error statusCode="406" prefixLanguageFilePath="E:\inetpub\custerr" path="406.htm" />
            <error statusCode="412" prefixLanguageFilePath="E:\inetpub\custerr" path="412.htm" />
            <error statusCode="500" prefixLanguageFilePath="E:\inetpub\custerr" path="500.htm" />
            <error statusCode="501" prefixLanguageFilePath="E:\inetpub\custerr" path="501.htm" />
            <error statusCode="502" prefixLanguageFilePath="E:\inetpub\custerr" path="502.htm" />
</httpErrors>

 

Summary

Custom and Detailed Errors are powerful IIS7 features. They help you to troubleshoot problems without compromising the security of your IIS7 Server. Plentiful configuration options help you to custom tailor the experience of your users. But most importantly: playing around with it is fun.

 

 

 

Comments

  1. Submitted on Apr 13 2008 by
    guzarva16@hotmail.com
    massage field is manual
  2. Submitted on Sep 15 2008 by
    plastic
    is there some way to configure iis7 to show
    "HTTP/1.1 413 msg" status instead of
    "HTTP/1.1 404 Not Found" and "404.13" in content area?
  3. Submitted on Sep 15 2008 by
    steve schofield
    Please submit your question in http://forums.iis.net/1052.aspx
  4. Submitted on Mar 15 2009 by
    tom88

    HTTP Error 404.3 - Not Found
    The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

    please help me.
    I use IIS7, but my VS2008 web application get above error.

    thanks

You must Log In to comment.