#include "AccessLogEntry.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "MemBuf.h"
#include "proxyp/Header.h"
#include "SquidConfig.h"
#include "ssl/support.h"
safe_free(adapt.last_meta);
#endif
- safe_free(headers.reply);
-
safe_free(headers.adapted_request);
HTTPMSGUNLOCK(adapted_request);
safe_free(lastAclName);
- HTTPMSGUNLOCK(reply);
HTTPMSGUNLOCK(request);
#if ICAP_CLIENT
HTTPMSGUNLOCK(icap.reply);
return nullptr;
}
+void
+AccessLogEntry::packReplyHeaders(MemBuf &mb) const
+{
+ if (reply)
+ reply->packHeadersUsingFastPacker(mb);
+}
+
void syncNotes(HttpRequest *request);
+ /// dump all reply headers (for sending or risky logging)
+ void packReplyHeaders(MemBuf &mb) const;
+
SBuf url;
/// TCP/IP level details about the client connection
public:
char *request = nullptr; //< virgin HTTP request headers
char *adapted_request = nullptr; //< HTTP request headers after adaptation and redirection
- char *reply = nullptr;
} headers;
#if USE_ADAPTATION
SBuf lastAclData; ///< string for external_acl_type %DATA format code
HierarchyLogEntry hier;
- HttpReply *reply = nullptr;
+ HttpReplyPointer reply;
HttpRequest *request = nullptr; //< virgin HTTP request
HttpRequest *adapted_request = nullptr; //< HTTP request after adaptation and redirection
if (reply && !al->reply) {
showDebugWarning("HttpReply object");
al->reply = reply;
- HTTPMSGLOCK(al->reply);
}
#if USE_IDENT
al.adapted_request = adapted_request_;
HTTPMSGLOCK(al.adapted_request);
- if (adapted_reply_) {
- al.reply = adapted_reply_;
- HTTPMSGLOCK(al.reply);
- } else
- al.reply = NULL;
+ // XXX: This reply (and other ALE members!) may have been needed earlier.
+ al.reply = adapted_reply_;
if (h->rfc931.size())
al.cache.rfc931 = h->rfc931.termedBuf();
if (replyHttpBodySize >= 0)
al.cache.highOffset = replyHttpBodySize;
//don't set al.cache.objectSize because it hasn't exist yet
-
- MemBuf mb;
- mb.init();
- adapted_reply_->header.packInto(&mb);
- al.headers.reply = xstrdup(mb.buf);
- mb.clean();
}
prepareLogWithRequestDetails(adapted_request_, alep);
Xaction::finalizeLogInfo();
if (IcapLogfileStatus == LOG_ENABLE) {
ACLFilledChecklist checklist(NULL, al->adapted_request, NULL);
if (al->reply) {
- checklist.reply = al->reply;
+ checklist.reply = al->reply.getRaw();
HTTPMSGLOCK(checklist.reply);
}
accessLogLogTo(Config.Log.icaplogs, al, &checklist);
if (request) {
SBuf matched;
for (auto h: Config.notes) {
- if (h->match(request, al->reply, al, matched)) {
+ if (h->match(request, al->reply.getRaw(), al, matched)) {
request->notes()->add(h->key(), matched);
debugs(33, 3, h->key() << " " << matched);
}
ACLFilledChecklist checklist(NULL, request, NULL);
if (al->reply) {
- checklist.reply = al->reply;
+ checklist.reply = al->reply.getRaw();
HTTPMSGLOCK(checklist.reply);
}
ACLFilledChecklist statsCheck(Config.accessList.stats_collection, request, NULL);
statsCheck.al = al;
if (al->reply) {
- statsCheck.reply = al->reply;
+ statsCheck.reply = al->reply.getRaw();
HTTPMSGLOCK(statsCheck.reply);
}
updatePerformanceCounters = statsCheck.fastCheck().allowed();
void
ConnStateData::sendControlMsg(HttpControlMsg msg)
{
+ if (const auto context = pipeline.front()) {
+ if (context->http)
+ context->http->al->reply = msg.reply;
+ }
+
if (!isOpen()) {
debugs(33, 3, HERE << "ignoring 1xx due to earlier closure");
return;
reply = http->storeEntry()->getReply()->clone();
HTTPMSGLOCK(reply);
+ http->al->reply = reply;
+
if (reply->sline.protocol == AnyP::PROTO_HTTP) {
/* RFC 2616 requires us to advertise our version (but only on real HTTP traffic) */
reply->sline.version = Http::ProtocolVersion();
sc->setDelayId(DelayId::DelayClient(http,reply));
#endif
- /* handle headers */
-
- if (Config.onoff.log_mime_hdrs) {
- size_t k;
-
- if ((k = headersEnd(buf, reqofs))) {
- safe_free(http->al->headers.reply);
- http->al->headers.reply = (char *)xcalloc(k + 1, 1);
- xstrncpy(http->al->headers.reply, buf, k);
- }
- }
-
holdingBuffer = result;
processReplyAccess();
return;
storeEntry()->replaceHttpReply(new_rep);
storeEntry()->timestampsSet();
+ al->reply = new_rep;
+
if (!adaptedBodySource) // no body
storeEntry()->complete();
clientGetMoreData(node, this);
assert(rep);
theVirginReply = rep;
HTTPMSGLOCK(theVirginReply);
+ if (fwd->al)
+ fwd->al->reply = theVirginReply;
return theVirginReply;
}
assert(rep);
theFinalReply = rep;
HTTPMSGLOCK(theFinalReply);
+ if (fwd->al)
+ fwd->al->reply = theFinalReply;
// give entry the reply because haveParsedReplyHeaders() expects it there
entry->replaceHttpReply(theFinalReply, false); // but do not write yet
ACLFilledChecklist ch(acl, originalRequest().getRaw());
ch.reply = const_cast<HttpReply*>(entry->getReply()); // ACLFilledChecklist API bug
HTTPMSGLOCK(ch.reply);
+ ch.al = fwd->al;
if (!ch.fastCheck().allowed()) { // when in doubt, block
debugs(20, 3, "store_miss prohibits caching");
return true;
static const Http::Message *
actualReplyHeader(const AccessLogEntry::Pointer &al)
{
- const Http::Message *msg = al->reply;
+ const Http::Message *msg = al->reply.getRaw();
#if ICAP_CLIENT
// al->icap.reqMethod is methodNone in access.log context
if (!msg && al->icap.reqMethod == Adaptation::methodReqmod)
} else
#endif
{
+ // just headers without start-line and CRLF
+ // XXX: reconcile with '<h'
out = al->headers.request;
quote = 1;
}
break;
case LFT_ADAPTED_REQUEST_ALL_HEADERS:
+ // just headers without start-line and CRLF
+ // XXX: reconcile with '<h'
out = al->headers.adapted_request;
quote = 1;
break;
- case LFT_REPLY_ALL_HEADERS:
- out = al->headers.reply;
+ case LFT_REPLY_ALL_HEADERS: {
+ MemBuf allHeaders;
+ allHeaders.init();
+ // status-line + headers + CRLF
+ // XXX: reconcile with '>h' and '>ha'
+ al->packReplyHeaders(allHeaders);
+ sb.assign(allHeaders.content(), allHeaders.contentSize());
+ out = sb.c_str();
#if ICAP_CLIENT
if (!out && al->icap.reqMethod == Adaptation::methodReqmod)
out = al->headers.adapted_request;
#endif
quote = 1;
- break;
+ }
+ break;
case LFT_USER_NAME:
#if USE_AUTH
void
HttpStateData::handle1xx(HttpReply *reply)
{
+ if (fwd->al)
+ fwd->al->reply = reply;
+
HttpReply::Pointer msg(reply); // will destroy reply if unused
// one 1xx at a time: we must not be called while waiting for previous 1xx
if (Config.onoff.log_mime_hdrs) {
char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
- char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
+ MemBuf mb;
+ mb.init();
+ al->packReplyHeaders(mb);
+ auto erep = ::Format::QuoteMimeBlob(mb.content());
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
if (Config.onoff.log_mime_hdrs) {
char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
- char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
+ MemBuf mb;
+ mb.init();
+ al->packReplyHeaders(mb);
+ auto erep = ::Format::QuoteMimeBlob(mb.content());
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
if (Config.onoff.log_mime_hdrs) {
char *ereq = ::Format::QuoteMimeBlob(al->headers.request);
- char *erep = ::Format::QuoteMimeBlob(al->headers.reply);
+ MemBuf mb;
+ mb.init();
+ al->packReplyHeaders(mb);
+ auto erep = ::Format::QuoteMimeBlob(mb.content());
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
Http::StreamPointer context = pipeline.front();
assert(context != nullptr);
- if (context->http && context->http->al != NULL &&
- !context->http->al->reply && reply) {
- context->http->al->reply = reply;
- HTTPMSGLOCK(context->http->al->reply);
- }
-
static ReplyHandler handlers[] = {
NULL, // fssBegin
NULL, // fssConnected
}
assert(rep);
- HTTPMSGUNLOCK(http->al->reply);
- http->al->reply = rep;
- HTTPMSGLOCK(http->al->reply);
context->sendStartOfMessage(rep, receivedData);
}