/*
- * $Id: http.cc,v 1.542 2007/12/14 23:11:47 amosjeffries Exp $
+ * $Id: http.cc,v 1.543 2007/12/26 23:39:55 hno Exp $
*
* DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
* AUTHOR: Harvest Derived
#include "DelayPools.h"
#endif
#include "SquidTime.h"
+#include "TextException.h"
+
+#define SQUID_ENTER_THROWING_CODE() try {
+#define SQUID_EXIT_THROWING_CODE(status) \
+ status = true; \
+ } \
+ catch (const TextException &e) { \
+ debugs (11, 1, "Exception error:" << e.message); \
+ status = false; \
+ }
CBDATA_CLASS_INIT(HttpStateData);
HttpHeader * hdr_out, int we_do_ranges, http_state_flags);
HttpStateData::HttpStateData(FwdState *theFwdState) : ServerStateData(theFwdState),
- header_bytes_read(0), reply_bytes_read(0)
+ header_bytes_read(0), reply_bytes_read(0), httpChunkDecoder(NULL)
{
debugs(11,5,HERE << "HttpStateData " << this << " created");
ignoreCacheControl = false;
entry->setNoDelay(_peer->options.no_delay);
#endif
-
}
/*
delete readBuf;
+ if(httpChunkDecoder)
+ delete httpChunkDecoder;
+
HTTPMSGUNLOCK(orig_request);
debugs(11,5, HERE << "HttpStateData " << this << " destroyed; FD " << fd);
readBuf->consume(header_bytes_read);
}
+ flags.chunked = 0;
+ if (newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) {
+ flags.chunked = 1;
+ httpChunkDecoder = new ChunkedCodingParser;
+ }
+
HttpReply *vrep = setVirginReply(newrep);
flags.headers_parsed = 1;
if (!flags.headers_parsed)
return INCOMPLETE_MSG;
+ /* In chunked responce we do not know the content length but we are absolutelly
+ * sure about the end of response, so we are calling the statusIfComplete to
+ * decide if we can be persistant
+ */
+ if (eof && flags.chunked)
+ return statusIfComplete();
+
if (eof) // already reached EOF
return COMPLETE_NONPERSISTENT_MSG;
{
const char *data = readBuf->content();
int len = readBuf->contentSize();
-
addVirginReplyBody(data, len);
readBuf->consume(len);
+}
+bool
+HttpStateData::decodeAndWriteReplyBody()
+{
+ const char *data = NULL;
+ int len;
+ bool status = false;
+ assert(flags.chunked);
+ assert(httpChunkDecoder);
+ SQUID_ENTER_THROWING_CODE();
+ MemBuf decodedData;
+ decodedData.init();
+ const bool done = httpChunkDecoder->parse(readBuf,&decodedData);
+ len = decodedData.contentSize();
+ data=decodedData.content();
+ addVirginReplyBody(data, len);
+ if (done) {
+ eof = 1;
+ flags.do_next_read = 0;
+ }
+ SQUID_EXIT_THROWING_CODE(status);
+ return status;
}
/*
* That means header content has been removed from readBuf and
* it contains only body data.
*/
- writeReplyBody();
+ if(flags.chunked){
+ if(!decodeAndWriteReplyBody()){
+ flags.do_next_read = 0;
+ serverComplete();
+ return;
+ }
+ }
+ else
+ writeReplyBody();
if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
/*
/*
- * $Id: http.h,v 1.32 2007/08/09 23:30:53 rousskov Exp $
+ * $Id: http.h,v 1.33 2007/12/26 23:39:55 hno Exp $
*
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
#include "comm.h"
#include "forward.h"
#include "Server.h"
+#include "ChunkedCodingParser.h"
class HttpStateData : public ServerStateData
{
virtual void handleRequestBodyProducerAborted();
void writeReplyBody();
+ bool decodeAndWriteReplyBody();
void doneSendingRequestBody();
void requestBodyHandler(MemBuf &);
virtual void sentRequestBody(int fd, size_t size, comm_err_t errflag);
http_state_flags flags);
static bool decideIfWeDoRanges (HttpRequest * orig_request);
+ ChunkedCodingParser *httpChunkDecoder;
private:
CBDATA_CLASS2(HttpStateData);
};