Better reporting of REQMOD failures during body processing. When REQMOD body processing fails, the server-side needs to abort the in-progress transaction. Use HTTP 500 (Internal Server Error) instead of 502 (Bad Gateway) status code and a new custom error detail for this case. The HTTP 500 (Internal Server Error) is more appropriate because most deployments consider adaptation to be a "part of the proxy service" rather than an "external gateway". And the custom error detail carries more information than a potentially stale and often irrelevant errno global. === modified file 'src/err_detail_type.h' --- src/err_detail_type.h 2010-12-15 17:52:35 +0000 +++ src/err_detail_type.h 2011-03-22 18:14:13 +0000 @@ -1,29 +1,30 @@ #ifndef _SQUID_ERR_DETAIL_H #define _SQUID_ERR_DETAIL_H typedef enum { ERR_DETAIL_NONE, ERR_DETAIL_START = 100000, // to avoid clashes with most OS error numbers ERR_DETAIL_CLT_REQMOD_ABORT = ERR_DETAIL_START, // client-side detected transaction abort ERR_DETAIL_CLT_REQMOD_REQ_BODY, // client-side detected REQMOD request body adaptation failure ERR_DETAIL_CLT_REQMOD_RESP_BODY, // client-side detected REQMOD satisfaction reply body failure + ERR_DETAIL_SRV_REQMOD_REQ_BODY, // server-side detected REQMOD request body abort ERR_DETAIL_ICAP_RESPMOD_EARLY, // RESPMOD failed w/o store entry ERR_DETAIL_ICAP_RESPMOD_LATE, // RESPMOD failed with a store entry ERR_DETAIL_REQMOD_BLOCK, // REQMOD denied client access ERR_DETAIL_RESPMOD_BLOCK_EARLY, // RESPMOD denied client access to HTTP response, before any part of the response was sent ERR_DETAIL_RESPMOD_BLOCK_LATE, // RESPMOD denied client access to HTTP response, after [a part of] the response was sent ERR_DETAIL_ICAP_XACT_START, // transaction start failure ERR_DETAIL_ICAP_XACT_BODY_CONSUMER_ABORT, // transaction body consumer gone ERR_DETAIL_ICAP_INIT_GONE, // initiator gone ERR_DETAIL_ICAP_XACT_CLOSE, // ICAP connection closed unexpectedly ERR_DETAIL_ICAP_XACT_OTHER, // other ICAP transaction errors ERR_DETAIL_EXCEPTION_OTHER, //other errors ( eg std C++ lib errors) ERR_DETAIL_MAX, ERR_DETAIL_EXCEPTION_START = 110000 // offset for exception ID details } err_detail_type; extern const char *err_detail_type_str[]; inline const char *errorDetailName(int errDetailId) { === modified file 'src/http.cc' --- src/http.cc 2011-03-09 17:44:55 +0000 +++ src/http.cc 2011-03-22 18:15:02 +0000 @@ -34,40 +34,41 @@ */ /* * Anonymizing patch by lutz@as-node.jena.thur.de * have a look into http-anon.c to get more informations. */ #include "squid.h" #include "acl/FilledChecklist.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #include "base/AsyncJobCalls.h" #include "base/TextException.h" #include "base64.h" #include "comm/Write.h" #if USE_DELAY_POOLS #include "DelayPools.h" #endif +#include "err_detail_type.h" #include "errorpage.h" #include "http.h" #include "HttpControlMsg.h" #include "HttpHdrContRange.h" #include "HttpHdrSc.h" #include "HttpHdrScTarget.h" #include "HttpReply.h" #include "HttpRequest.h" #include "MemBuf.h" #include "MemObject.h" #include "protos.h" #include "rfc1738.h" #include "SquidTime.h" #include "Store.h" #define SQUID_ENTER_THROWING_CODE() try { #define SQUID_EXIT_THROWING_CODE(status) \ status = true; \ } \ @@ -2287,42 +2288,46 @@ debugs(11, 1, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << orig_request->client_addr << "' -> '" << entry->url() << "'" ); if (virginReply()->sline.status == HTTP_INVALID_HEADER) { comm_close(fd); return; } } } HttpStateData::handleMoreRequestBodyAvailable(); } // premature end of the request body void HttpStateData::handleRequestBodyProducerAborted() { ServerStateData::handleRequestBodyProducerAborted(); if (entry->isEmpty()) { debugs(11, 3, "request body aborted: FD " << fd); ErrorState *err; - err = errorCon(ERR_READ_ERROR, HTTP_BAD_GATEWAY, fwd->request); - err->xerrno = errno; + // We usually get here when ICAP REQMOD aborts during body processing. + // We might also get here if client-side aborts, but then our response + // should not matter because either client-side will provide its own or + // there will be no response at all (e.g., if the the client has left). + err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, fwd->request); + err->xerrno = ERR_DETAIL_SRV_REQMOD_REQ_BODY; fwd->fail(err); } abortTransaction("request body producer aborted"); } // called when we wrote request headers(!) or a part of the body void HttpStateData::sentRequestBody(const CommIoCbParams &io) { if (io.size > 0) kb_incr(&statCounter.server.http.kbytes_out, io.size); ServerStateData::sentRequestBody(io); } // Quickly abort the transaction // TODO: destruction should be sufficient as the destructor should cleanup, // including canceling close handlers void