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