Hi everyone,
I wrote a ISAPI filter DLL to process text/html content. Whenever there's a request for a .php file, the OnUrlMap gets called 3 times whereas .html or .asp files causes the right behaviour in Filter (i.e. - OnUrlMap gets called once only). How do I get rid off this problem? Below is the excerpt of the code -
DWORD OnSendRawData(...) { //Process pvRawData.... ........ //Writes HTTP HEADER to client pfc->WriteClient(....); //Writes BODY //pfc->WriteClient(...);}
When the code executes for HTTP HEADER, the function gets suspended and the second request of the .php file calls OnSendRawData. When any Win32 API gets called in the OnSendRawData code, the second request is suspended and the first one is resumed (i.e.- starts writing the BODY).
As both are same actually request, it messed up the private (or content specific) data.
So, How to stop multiple request in OnUrlMap?
Actually, the behaviors you describe are all by-design.
There is no guarantee that every event fires at least once per request. There is also no guarantee that every event fires at most once. In fact, the following events can fire multiple times per request:
Thus, your assumption that the "right" behavior for OnUrlMap is getting called once per request... is incorrect. You also assume that OnSendRawData gets called once per request and that no user code can trigger multiple calls to it... and that is incorrect.
This is how the events actually work:
SF_NOTIFY_READ_RAW_DATA happens each time a data packet is read from the client (assuming either IIS6 running in IIS5 Compatibility Mode or prior IIS versions). This happens at least once per request (to read in the headers), and depending on how the headers are sent and the size of the request entity body, additional events can be triggered by IIS buffering up to W3SVC/UploadReadAheadSize or by ISAPIs making ReadClient() calls. Only the first trigger of this event is guaranteed to happen before any response has been sent to the client; any other trigger of this event can obviously happen at any time during request processing.
SF_NOTIFY_URL_MAP happens each time IIS or user-code requests a URL-to-physical mapping of a URL. This happens at least once per request because IIS has to do the URL-to-physical mapping to obtain the physical resource to process. It can also happen for other reasons, such as:
SF_NOTIFY_SEND_RESPONSE happens each time IIS or user-code sends structured response headers.
SF_NOTIFY_SEND_RAW_DATA happens each time IIS or user-code sends data to the client.
I am not certain whether your Filter has bugs in OnUrlMap or OnSendRawData, but the code snippet you show is definitely wrong. In general, it is a bad idea to call WriteClient() from OnSendRawData because WriteClient() triggers OnSendRawData... so your code has to somehow WriteClient HTTP_HEADER, and when that WriteClient() triggers OnSendRawData, remember to NOT WriteClient HTTP_HEADER... and so on. Yeah, complicated. Good luck.
Since you are trying to process response content, I assume you are trying to buffer the response with OnSendRawData, make the appropriate modifications, and then flush the modifications to the client. There are a couple of approaches:
The first approach is easy to implement but buffers the entire response, which can be resource-intensive on large responses/downloads. The second approach is more complicated to implement but only buffers the necessary amount of data to perform necessary modifications.
//David