I'm having some problems with Squid's ICAP client breaking on RESPMOD
when handling responses with a body exactly 1 octet long.
- The browser makes a request to Squid
- Squid makes a request to the web server and receives back a response
with a "Content-Length: 1" header and a 1 octet body.
- The response gets sent to the ICAP server, which replies with a "204
No Modifications".
- Squid sends the response on to the browser, with the "Content-Length:
1" header intact, but doesn't send a body. The browser sits there
indefinitely waiting for the body to appear.
As far as I can tell, the ICAP client successfully copies the body from
the virgin response to the adapted response.
The problem appears to be with
ServerStateData::handleMoreAdaptedBodyAvailable() - The API for
StoreEntry::bytesWanted() seems to be that it will return 0 if it wants
no data, or up to aRange.end-1 if more data is wanted. This means that
if aRange.end == 1, which is the case when we only have 1 octet of data,
it is always going to look like it can't accept any more data.
The fact that it can't accept a single octet is actually noted in
ServerStateData::handleMoreAdaptedBodyAvailable() in Server.cc:
// XXX: bytesWanted API does not allow us to write just one byte!
I've resolved this problem by changing the following lines in
ServerStateData::handleMoreAdaptedBodyAvailable():
const size_t bytesWanted = entry->bytesWanted(Range<size_t>(0,
contentSize));
const size_t spaceAvailable = bytesWanted > 0 ? (bytesWanted + 1) : 0;
To:
const size_t spaceAvailable = entry->bytesWanted(Range<size_t>(0,
contentSize+1));
(Patch attached)
However, I'm not sure if this is a correct fix - what effect does adding
1 to the contentSize given to bytesWanted() actually have? And is this
supposed to be handled elsewhere?
--
- Steve Hill
Technical Director
Opendium Limited http://www.opendium.com
Direct contacts:
Instant messager: xmpp:steve@xxxxxxxxxxxx
Email: steve@xxxxxxxxxxxx
Phone: sip:steve@xxxxxxxxxxxx
Sales / enquiries contacts:
Email: sales@xxxxxxxxxxxx
Phone: +44-844-9791439 / sip:sales@xxxxxxxxxxxx
Support contacts:
Email: support@xxxxxxxxxxxx
Phone: +44-844-4844916 / sip:support@xxxxxxxxxxxx
Index: src/Server.cc
===================================================================
--- src/Server.cc (revision 115)
+++ src/Server.cc (working copy)
@@ -723,8 +723,7 @@
// XXX: entry->bytesWanted returns contentSize-1 if entry can accept data.
// We have to add 1 to avoid suspending forever.
- const size_t bytesWanted = entry->bytesWanted(Range<size_t>(0, contentSize));
- const size_t spaceAvailable = bytesWanted > 0 ? (bytesWanted + 1) : 0;
+ const size_t spaceAvailable = entry->bytesWanted(Range<size_t>(0, contentSize+1));
if (spaceAvailable < contentSize ) {
// No or partial body data consuming
@@ -734,8 +733,7 @@
entry->deferProducer(call);
}
- // XXX: bytesWanted API does not allow us to write just one byte!
- if (!spaceAvailable && contentSize > 1) {
+ if (!spaceAvailable && contentSize > 0) {
debugs(11, 5, HERE << "NOT storing " << contentSize << " bytes of adapted " <<
"response body at offset " << adaptedBodySource->consumedSize());
return;