Hi Angus,

With one bug fix to reset the stream to the start, your code worked fine
thanks.

Don't know if this is really a bug, or if the need to reset it correspond to a not standard way to deal with streams by the HTTPServer component. In order to enhance the AnswerStream functionality I think the responsibility to set the stream start position must be passed to the code that assign the stream (and that's the standard way to do it), and content-length must be calculated by stream.size-stream.position, but because the called sendstream also reset the stream position, you are right and we must follow this rule here. Even so, streams are to be used the other way. Changing to standard behavior is, IMHO, advantageous.

However, content encoding needs to be done in SendDocument as well as
AnswerStream (that got me confused during testing, it worked first page,
but not again).

Yes :-)), I just adapted my, quick fix, code, used in one of my projects, trying to set it more generic, but forgot to add it to the SendDocument. I'm using compression only in dynamically calculated responses, not in file documents.

I've added options so content coding is configurable,
with slightly different events to allow cached compressed files to be
used, it was in SVN last night.
And, in general, I like it ;-) Really good enhancements on top of my simple draft code!

Even so I think that if OnContentEncode is assigned, the responsibility to decide if the content-type and stream size are viable to encode (and encode isn't always compression), must be passed to this external event. These content-type and stream size options must be taken into account only by internal compression code, if not handled externally.


Sadly you removed the possibility to completely exclude linkage to ICS ZLib :( The workaround to use the ZLibDll could work, but this unit is loading the DLL at initialization, doing something not needed if application is not going to use compression (no hoContentEncoding in server.options), or if using its own encoding thru the OnContentEncode event. This also pose a problem, because code is calling DLL functions without checking if library loaded successfully. So I think you could add a conditional compilation check to stop loading the DLL at the unit initialization (not breaking existing code that relies on this already loaded behavior), and add a boolean ZLIbLoaded function to ZLibLoadDll in order to use it like this: (Next code also include my talked above, delegate to event decision to encode, idea.)
...
   if not Assigned(FDocStream) then
       PutStringInSendBuffer('Content-Length: 0' + #13#10)
   else begin
if hoContentEncoding in FServer.Options then begin { V7.20 are we allowed to compress content }
           CompressionHandled := false;
TriggerContentEncode(ContentEncoding, CompressionHandled); { let application do it, or find cached file }
             if CompressionHandled then
PutStringInSendBuffer('Content-Encoding: ' + ContentEncoding + #13#10)
               else
if ((ContType = '') or (Pos ('text/', ContType) > 0)) and { only compress textual stuff } ((FDocStream.Size >= FServer.SizeCompressMin) and { too small a waste of time } (FDocStream.Size < FServer.SizeCompressMax)) then begin { too large will block server and use a lot of memory }
                   if Pos('deflate', FRequestAcceptEncoding) > 0 then begin
PutStringInSendBuffer('Content-Encoding: deflate' + #13#10);
                       ZStreamType := zsRaw;
                   end
else if Pos('gzip', FRequestAcceptEncoding) > 0 then begin PutStringInSendBuffer('Content-Encoding: gzip' + #13#10);
                       ZStreamType := zSGZip;
                   end
                   else
                       ZStreamType := zsZLib;
if (ZStreamType <> zsZLib) {$IFNDEF USE_ZLIB_OBJ}and ZLibLoaded {$ENDIF} then begin
                       ZDocStream := TMemoryStream.Create;
                       FDocStream.Seek (0, 0); { reset to start }
ZlibCompressStreamEx(FDocStream, ZDocStream, clDefault, ZStreamType, true);
                       FDocStream.free;
                       FDocStream := ZDocStream;
TriggerContEncoded; { let application cache compressed file or report what we did }
                   end;
           end;
       end;
PutStringInSendBuffer('Content-Length: ' + _IntToStr(FDocStream.Size) + #13#10);
...


With this new function in OverbyteIcsZLibDll

Function ZLIbLoaded:boolean;
begin
if zlibDllLoaded then
result:=true
else begin
  ZLibLoadDll(ZLibDllName);
  result:=zlibDllLoaded;
end
end;



Just my 2c. You, and Francois, are the ones who have to decide. Lucky me ;-)

Regards,
Rui

--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to