Microsoft IIS has a limitation that has been causing headaches for anyone who works with both Unix and Windows web servers. IIS only supports one default document name. You can configure it to look for default.htm, or index.html, but not both. On Unix servers running NCSA or Apache, you can specify a list of default document names and the server checks for each one in order.
This matters because Unix web sites use index.html by convention, and IIS sites use default.htm. When you migrate a site from Unix to IIS, or when you have content that was authored for both platforms, you end up with directories that have index.html files but no default.htm. A user browsing to that directory gets an error or a directory listing instead of the page they should see.
I wrote a solution: an ASP script called default-index.asp. You set this as your default document in IIS, and when a user requests a directory, the script checks for files in this order:
- index.html
- default.htm
- index.shtml
If it finds one, it serves that file. If none of them exist, the user gets a normal error. It is a simple script, just a few lines of ASP, but it solves the problem completely.
default.asp → checks for index.html → default.htm → index.shtml
The way it works is that IIS calls default-index.asp as the default document. The ASP script then uses the FileSystemObject to check whether each candidate file exists in the current directory. When it finds one, it does a Server.Transfer to serve that file. The user never knows the ASP script was involved.
I put this on my web site when I wrote it, and it turned out to be the only solution available for this problem for quite a while. It was listed on the ASP Developers FAQ as the way to handle multiple default documents on IIS. I have gotten email from web administrators at various organizations saying they use it.
I had started writing an ISAPI filter version, which would be faster because it runs as a native DLL inside IIS rather than being interpreted as ASP on each request. But Microsoft’s upcoming IIS 4.0 beta is supposed to have native support for multiple default documents built into the server. If they do it right, my script becomes unnecessary, which is fine. The best outcome for a workaround is that the vendor fixes the underlying problem.
Until IIS 4.0 ships, though, default-index.asp does the job. You can get it from http://rajiv.org/free/.
Here is the full source code:
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
' File Name: default.asp
' Language: VBScript (Server Side)
' Purpose: Allows multiple default documents in Microsoft IIS WWW Service.
' Requires: Microsoft IIS 3.0 with Active Server Pages.
' Author: Rajiv Pant (Betul) [email protected] http://rajiv.org
' A better soultion than this would be use an ISAPI filter DLL to enable
' multiple default documents. I will post an example of that here.
' How to use: Set your IIS default document to the name of this file.
' (You can give any name to this file.) Then have a script
' place a copy of this file in every folder under your document
' root. (That is why the ISAPI version I'm writing is a better solution.)
' Note: You may want to modify this program to go through a list
' of default documents taking different kinds of actions for
' that type of default document.
' This system is useful for NT/IIS based ISPs that host many
' people's sites, some of which may be migrating from Unix
' based web servers. This way, people can continue using the
' default documents they were used to.
On Error Resume Next
doc = "index.html" ' We first look for index.html
set FileObject = Server.CreateObject ("Scripting.FileSystemObject")
Selected = FALSE
while NOT Selected
strFilename = Server.MapPath (doc) ' The physical path to the file doc
Err.clear
set oInStream = FileObject.OpenTextFile (strFilename, 1, FALSE, FALSE)
If (Err.number > 0) then
Select Case doc
' If index.html is not found, we look for index.stm
Case "index.html" doc = "index.stm"
' If index.stm is not found, we look for index.shtml
Case "index.stm" doc = "index.shtml"
' If index.shtml is not found, we look for index.htm
Case "index.shtml" doc = "index.htm"
' If index.htm is not found, we look for default.htm
Case "index.htm" doc = "default.htm"
' If default.htm is not found, we look for index.txt
Case "default.htm" doc = "index.txt"
' If index.txt is not found, we look for index.asp
Case "index.txt" doc = "index.asp"
' If even the last default document in our list is not found,
' we set doc to empty and use that to take certain action later.
Case Else doc = ""
Selected = TRUE
End Select
Else Selected = TRUE
End If
Wend
If doc = "" Then
' Now we could either display the directory like many web servers do,
' or we could just give a message as we do below.
Response.Write ("No default document found.<br>")
Else
If doc = "index.html" or doc = "index.htm" or doc = "default.htm" Then
' For .html, .htm, and other non-server-parsed files,
' open the file and print out it's contents. This way, the URL will
' not change and the browser will not have to do a redirection.
While NOT oInstream.AtEndOfStream
Response.Write (oInstream.Readline)
oInstream.Skipline()
Wend
Set oInstream = nothing
Else ' server-parsed or some other type of document
' For .stm, .shtml, .asp, .htx and other server-parsed or other files, redirect
' the browser to that file.
Response.Redirect (doc)
End If ' server-parsed or non-server-parsed document
End If
</SCRIPT>