Question:

My web server was recently upgraded from Win2K to Win2003 and I've noticed a change in the way Server Side Includes (SSI) operate. In Win2K a script called via #exec was run as if it were part of the calling SSI file. This had two affects when the script that is run is an ASP file:

- Request.ServerVariables("PATH_INFO") returned the name of the SSI file

- Request.Querytring accessed the querystring associated with the SSI file

In effect, the parameters of the original SSI file are passed through to the script that is executed. In Win2003 this is no longer the case. PATH_INFO indicates the ASP file and Request.Querystring does not display anything (unless one is appended to the end of the #exec statement).

I was curious if these changes were by design and if there is a way to restore the old model (such as a metabase setting). The only alternative method I currently see available to me is working out a JavaScript method of generating the content I need or associating the HTML files with the ASP processor (and using Server.Execute).

Thanks for your time.

Answer:

Yes, the changes are by-design. Unfortunately, there is no way to restore the old model via configuration because it is intrinsic to how IIS functions internally. We would need to do some serious hacking of the IIS6 URL Execution model... which we declined to do.

FYI: The Exchange team had noticed the same behavior changes you described on IIS6 several years ago, but we declined their request as well. Same reasoning. They ended up implementing a work-around using our new model.

Without going into too much dirty details, let's just say that:

  • Child URL Execution was hacked into IIS5 and never clearly identified child vs. parent.
  • Child URL Execution is a fundamental built-in feature of IIS6, where child URL Execution is idempotent and separate from the parent.
  • Child URL Execution is used in functionality like #exec and Default Document resolution, amongst others

This is why IIS6 is able to expose HSE_REQ_EXEC_URL for ISAPI Extensions, but IIS5 exposes no such comparable API.

How the design appears to end users is that on IIS5, Child URL Execution is nested inside the parent's - thus, the child would see the parent's server variables, such as URL, PATH_INFO, and QUERY_STRING, and react just like the parent. On IIS6, Child URL Execution is completely new, so the child will see its own server variables. This means that the child URL has NO idea whether a parent URL invoked it, unless the parent altered some aspect of the child request to indicate it (such as added request headers, querystring, etc).

[Modified 12/23/2005] Ok, it appears that some people really want the details and want to know why #exec changed in IIS6... so here goes.

In every version of IIS until IIS6, ISAPI has had a huge functionality hole when it comes to doing filter-like operations (i.e. read/modify) on the incoming entity body. MANY people have tried to do this sort of thing improperly with SF_NOTIFY_READ_RAW_DATA for years with bad or inconsistent results... because that filter event was never designed for such use. Why do people want to filter the incoming entity body? Well... because users want to filter POSTed FORM variables/data as non-opaque entities... but SF_NOTIFY_READ_RAW_DATA was only designed for opaque data usage such as SSL decryption.

The new Child URL Execution model neatly solves this problem and makes it completely trivial for an ISAPI Extension configured as a wildcard application mapping to call HSE_REQ_EXEC_URL and filter the entire request from parent to child. The ISAPI can easily read/manipulate the incoming entity body, as well as headers, URLs, impersonation token, and authentication related ServerVariables like AUTH_TYPE and AUTH_USER, and then have IIS execute the request as if it was the original. In short, this new mechanism is heaven for people who want to write URL-Rewriters, Custom-Authentication, and Request Forwarders.

Unfortunately, the old Child URL Execution model had to be removed and replaced with the new one to accomplish this major feature and fill a functionality hole in ISAPI extensibility of IIS... so as a side-effect, SSI #exec behavior changed as well. For example, if HSE_REQ_EXEC_URL changed the URL, should the child see the old or new URL? From the perspective of "executing the changed request as if it was the original", it should be the new URL, but #exec would require the old URL.

It would be hard to impossible for us to make both models coincide and work, the number of people benefiting from filtered access to request entity body is great and highly visible... so the old Child URL Execution model lost out. Of course, if there is a compelling business reason for the old Child URL Execution model to return side-by-side in IIS6, we are certainly open to consider it.

In hindsight, what could be useful are new server variables like PARENT_URL and ANCESTOR_URL, which indicate the immediate parent URL that invoked the child as well as the very original URL. Then, the child could decide which set of server variable values that it wants, based on circumstance... but this is also getting close to being an edge-scenario...

//David