I recently got this question about the behavior of QUERY_STRING values. Unfortunately, server variable values are more a matter of art than science, as I will shortly describe...

Question:

Hi David,

I am having an interesting problem. I have written an ISAPI filter that pulls information like the REMOTE_ADDR, AUTH_USER, QUERY_STRING, SERVER_PORT, and SERVER_NAME. I store this information and pass it to another program that uses it.

The problem that I am having is that on IIS 6.0, everything works as I would expect. Unfortunately, I am not seeing the same behavior on IIS 5.0. I pull everything the same way except the QUERY_STRING always returns empty. I am pretty sure that it isn't the code around it because I can change it to ALL_RAW or AUTH_USER and get information printed.

I know that on ISA, the query string is not supported, but I am not using ISA. Am I missing something?

So I have checked other information on it, as well. The function is always returning TRUE in 2000 and 2003. I am checking the GetLastError just to make sure, and it returns a 0 also.

Any advice?

Thanks,

Answer:

When it comes to the expected value of a Server Variable, it completely depends on the filter event within which you retrieve the server variable and sometimes even ordering/timing.

For example, server variable values are not always populated right from the start. QUERY_STRING is not going to be populated in events like SF_NOTIFY_READ_RAW_DATA or SF_NOTIFY_PREPROC_HEADERS because IIS has not yet parsed the request and hence cannot legitimately populate that server variable. In those cases, IIS GetServerVariable() should return true and an empty string.

Now, you should note that server variable values will change over the lifetime of request processing. For example, it is possible on the second SF_NOTIFY_READ_RAW_DATA event to find QUERY_STRING populated and valid. This is because the first SF_NOTIFY_READ_RAW_DATA was for the headers (and QUERY_STRING is invalid since headers were not parsed yet), and after the headers are parsed and QUERY_STRING populated, the subsequent SF_NOTIFY_READ_RAW_DATA are for entity body - so QUERY_STRING would be rightfully valid.

Then again, sometimes IIS may return true and non-empty values for server variables in events that it should not... which is technically a bug, but if you tried to rely on those values, your ISAPI has a serious bug as well. For example, try to retrieve the REMOTE_ADDR server variable in SF_NOTIFY_END_OF_NET_SESSION, and it can come back with a valid value... but clearly, the connection has already ended, so the value is bogus and useless for communications usage.

Ordering also matters. For example, retrieving the PATH_TRANSLATED server variable will trigger participating SF_NOTIFY_URL_MAP filters who may/not manipulate pszPhysicalPath. This means that depending on arbitrary ISAPI Filter ordering/behavior, an ISAPI Filter can retrieve different values for PATH_TRANSLATED, even within the same filter event... and once again, this behavior is perfectly valid and permissible. A similar class of behavior exists with WriteClient() and SendResponseHeader because they allow a filter to prematurely trigger SF_NOTIFY_SEND_RAW_DATA and SF_NOTIFY_SEND_RESPONSE events, and the state of server variables may be different than the normal sequence.

So, the answer to your question really depends on what filter event and possibly ordering of other filters on IIS. But, I do not have that information so I cannot say for certain what is going on in your situation. I suspect you are looking at some quirks related to processing subsequent SF_NOTIFY_READ_RAW_DATA based on some of the behavior possibilities I described above.

FYI: since ISA Server's implementation of ISAPI Filter is completely separate and unrelated to IIS ISAPI Filter, I would not try to draw any sort of parallel expectations between them.

//David