From: Christos Tsantilas Date: Fri, 26 Oct 2012 19:42:31 +0000 (+0300) Subject: note option X-Git-Tag: SQUID_3_4_0_1~548 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d7f4a0b73b11fade7274e344c0293af319696459;p=thirdparty%2Fsquid.git note option This patch adds note option to squid.conf. It is similar to adaptation_meta but is applied after all adaptation and before logging. Values of key/value pair notes can be logged using %{key}note macros. note key value acl ... logformat myFormat ... %{key}note ... This option may be initially used to log custom information about the master transaction. For example, an admin may configure Squid to log which "user group" the transaction belongs to, where "user group" will be determined based on a set of ACLs and not [just] authentication information. From user point of view, adaptation_header sets/implies meta (i.e., setting adaptation_meta is sufficient to be able to log it using %note) but the note option itself (if any) is evaluated later, so it has no effect on ICAP headers. This is a Measurement Factory project --- diff --git a/src/AccessLogEntry.h b/src/AccessLogEntry.h index eb011e8ea0..8ed08f930c 100644 --- a/src/AccessLogEntry.h +++ b/src/AccessLogEntry.h @@ -32,6 +32,7 @@ #include "anyp/PortCfg.h" #include "comm/Connection.h" +#include "HttpHeader.h" #include "HttpVersion.h" #include "HttpRequestMethod.h" #include "HierarchyLogEntry.h" @@ -41,6 +42,7 @@ #if ICAP_CLIENT #include "adaptation/icap/Elements.h" #endif +#include "Notes.h" #include "RefCount.h" #if USE_SSL #include "ssl/gadgets.h" @@ -229,6 +231,8 @@ public: HttpReply *reply; HttpRequest *request; //< virgin HTTP request HttpRequest *adapted_request; //< HTTP request after adaptation and redirection + /// key:value pairs set by note and adaptation_meta + NotePairs notes; #if ICAP_CLIENT /** \brief This subclass holds log info for ICAP part of request diff --git a/src/HttpHeader.h b/src/HttpHeader.h index fc76880cdf..4def174193 100644 --- a/src/HttpHeader.h +++ b/src/HttpHeader.h @@ -175,6 +175,7 @@ typedef enum { #if USE_SSL hoErrorDetail, #endif + hoNote, hoEnd } http_hdr_owner_type; diff --git a/src/HttpHeaderTools.cc b/src/HttpHeaderTools.cc index a49091bb52..588f1c6902 100644 --- a/src/HttpHeaderTools.cc +++ b/src/HttpHeaderTools.cc @@ -31,12 +31,14 @@ */ #include "squid.h" +#include "globals.h" #include "acl/FilledChecklist.h" #include "acl/Gadgets.h" #include "client_side_request.h" #include "client_side.h" #include "comm/Connection.h" #include "compat/strtoll.h" +#include "ConfigParser.h" #include "fde.h" #include "HttpHdrContRange.h" #include "HttpHeader.h" diff --git a/src/Makefile.am b/src/Makefile.am index 7a6b3d0164..f908ed2394 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -440,6 +440,8 @@ squid_SOURCES = \ multicast.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Packer.h \ Parsing.cc \ @@ -1118,6 +1120,7 @@ TESTS += $(check_PROGRAMS) tests_testHttpReply_SOURCES=\ cbdata.cc \ cbdata.h \ + ConfigParser.cc \ ETag.cc \ fatal.h \ tests/stub_fatal.cc \ @@ -1491,6 +1494,8 @@ tests_testCacheManager_SOURCES = \ mime_header.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ pconn.cc \ @@ -1903,6 +1908,8 @@ tests_testEvent_SOURCES = \ multicast.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ pconn.cc \ @@ -2146,6 +2153,8 @@ tests_testEventLoop_SOURCES = \ multicast.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ pconn.cc \ @@ -2386,6 +2395,8 @@ tests_test_http_range_SOURCES = \ multicast.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ peer_digest.cc \ @@ -2668,6 +2679,8 @@ tests_testHttpRequest_SOURCES = \ mime_header.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ pconn.cc \ @@ -3761,6 +3774,8 @@ tests_testURL_SOURCES = \ mime_header.cc \ neighbors.h \ neighbors.cc \ + Notes.cc \ + Notes.h \ Packer.cc \ Parsing.cc \ pconn.cc \ diff --git a/src/SquidConfig.h b/src/SquidConfig.h index 746f697bee..40a8a235f8 100644 --- a/src/SquidConfig.h +++ b/src/SquidConfig.h @@ -36,6 +36,7 @@ #include "HttpHeaderTools.h" #include "icmp/IcmpConfig.h" #include "ip/Address.h" +#include "Notes.h" #include "RefCount.h" #include "YesNoNone.h" @@ -476,6 +477,8 @@ public: HeaderManglers *reply_header_access; ///request_header_add access list HeaderWithAclList *request_header_add; + ///note + Notes notes; char *coredump_dir; char *chroot_dir; #if USE_CACHE_DIGESTS diff --git a/src/adaptation/Config.cc b/src/adaptation/Config.cc index 0d3b86940f..5d233593d0 100644 --- a/src/adaptation/Config.cc +++ b/src/adaptation/Config.cc @@ -49,53 +49,24 @@ int Adaptation::Config::service_iteration_limit = 16; int Adaptation::Config::send_client_ip = false; int Adaptation::Config::send_username = false; int Adaptation::Config::use_indirect_client = true; -Adaptation::Config::MetaHeaders Adaptation::Config::metaHeaders; - -Adaptation::Config::MetaHeader::Value::~Value() -{ - aclDestroyAclList(&aclList); -} - -Adaptation::Config::MetaHeader::Value::Pointer -Adaptation::Config::MetaHeader::addValue(const String &value) -{ - Value::Pointer v = new Value(value); - values.push_back(v); - return v; -} - -const char * -Adaptation::Config::MetaHeader::match(HttpRequest *request, HttpReply *reply) -{ - - typedef Values::iterator VLI; - ACLFilledChecklist ch(NULL, request, NULL); - if (reply) - ch.reply = HTTPMSGLOCK(reply); - - for (VLI i = values.begin(); i != values.end(); ++i ) { - const int ret= ch.fastCheck((*i)->aclList); - debugs(93, 5, HERE << "Check for header name: " << name << ": " << (*i)->value - <<", HttpRequest: " << request << " HttpReply: " << reply << " matched: " << ret); - if (ret == ACCESS_ALLOWED) - return (*i)->value.termedBuf(); - } - return NULL; -} - -Adaptation::Config::MetaHeader::Pointer -Adaptation::Config::addMetaHeader(const String &headerName) -{ - typedef MetaHeaders::iterator AMLI; - for (AMLI i = metaHeaders.begin(); i != metaHeaders.end(); ++i) { - if ((*i)->name == headerName) - return (*i); - } - - MetaHeader::Pointer meta = new MetaHeader(headerName); - metaHeaders.push_back(meta); - return meta; -} +const char *metasBlacklist[] = { + "Methods", + "Service", + "ISTag", + "Encapsulated", + "Opt-body-type", + "Max-Connections", + "Options-TTL", + "Date", + "Service-ID", + "Allow", + "Preview", + "Transfer-Preview", + "Transfer-Ignore", + "Transfer-Complete", + NULL +}; +Notes Adaptation::Config::metaHeaders("ICAP header", metasBlacklist); Adaptation::ServiceConfig* Adaptation::Config::newServiceConfig() const @@ -180,8 +151,6 @@ Adaptation::Config::freeService() DetachServices(); serviceConfigs.clean(); - - FreeMetaHeader(); } void @@ -255,64 +224,6 @@ Adaptation::Config::Finalize(bool enabled) FinalizeEach(AllRules(), "message adaptation access rules"); } -void -Adaptation::Config::ParseMetaHeader(ConfigParser &parser) -{ - String name, value; - const char *warnFor[] = { - "Methods", - "Service", - "ISTag", - "Encapsulated", - "Opt-body-type", - "Max-Connections", - "Options-TTL", - "Date", - "Service-ID", - "Allow", - "Preview", - "Transfer-Preview", - "Transfer-Ignore", - "Transfer-Complete", - NULL - }; - ConfigParser::ParseString(&name); - ConfigParser::ParseQuotedString(&value); - - // TODO: Find a way to move this check to ICAP - for (int i = 0; warnFor[i] != NULL; ++i) { - if (name.caseCmp(warnFor[i]) == 0) { - fatalf("%s:%d: meta name \"%s\" is a reserved ICAP header name", - cfg_filename, config_lineno, name.termedBuf()); - } - } - - MetaHeader::Pointer meta = addMetaHeader(name); - MetaHeader::Value::Pointer headValue = meta->addValue(value); - aclParseAclList(parser, &headValue->aclList); -} - -void -Adaptation::Config::DumpMetaHeader(StoreEntry *entry, const char *name) -{ - typedef MetaHeaders::iterator AMLI; - for (AMLI m = metaHeaders.begin(); m != metaHeaders.end(); ++m) { - typedef MetaHeader::Values::iterator VLI; - for (VLI v =(*m)->values.begin(); v != (*m)->values.end(); ++v ) { - storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s", - name, SQUIDSTRINGPRINT((*m)->name), ConfigParser::QuoteString((*v)->value)); - dump_acl_list(entry, (*v)->aclList); - storeAppendPrintf(entry, "\n"); - } - } -} - -void -Adaptation::Config::FreeMetaHeader() -{ - metaHeaders.clean(); -} - void Adaptation::Config::ParseServiceSet() { diff --git a/src/adaptation/Config.h b/src/adaptation/Config.h index da3234b7a5..65061a325c 100644 --- a/src/adaptation/Config.h +++ b/src/adaptation/Config.h @@ -6,6 +6,7 @@ #include "base/AsyncCall.h" #include "adaptation/forward.h" #include "adaptation/Elements.h" +#include "Notes.h" #include "SquidString.h" class acl_access; @@ -23,9 +24,6 @@ public: static void ParseServiceSet(void); static void ParseServiceChain(void); - static void ParseMetaHeader(ConfigParser &parser); - static void FreeMetaHeader(); - static void DumpMetaHeader(StoreEntry *, const char *); static void ParseAccess(ConfigParser &parser); static void FreeAccess(void); @@ -50,53 +48,7 @@ public: time_t oldest_service_failure; int service_revival_delay; - /** - * Used to store meta headers. The meta headers are custom - * ICAP request headers or ECAP options used to pass custom - * transaction-state related meta information to a service. - */ - class MetaHeader: public RefCountable - { - public: - typedef RefCount Pointer; - /// Stores a value for the meta header. - class Value: public RefCountable - { - public: - typedef RefCount Pointer; - String value; ///< a header value - ACLList *aclList; ///< The access list used to determine if this value is valid for a request - explicit Value(const String &aVal) : value(aVal), aclList(NULL) {} - ~Value(); - }; - typedef Vector Values; - - explicit MetaHeader(const String &aName): name(aName) {} - - /** - * Adds a value to the meta header and returns a pointer to the - * related Value object. - */ - Value::Pointer addValue(const String &value); - - /** - * Walks through the possible values list of the meta and selects - * the first value which matches the given HttpRequest and HttpReply - * or NULL if none matches. - */ - const char *match(HttpRequest *request, HttpReply *reply); - String name; ///< The meta header name - Values values; ///< The possible values list for the meta header - }; - typedef Vector MetaHeaders; - static MetaHeaders metaHeaders; ///< The list of configured meta headers - - /** - * Adds a header to the meta headers list and returns a pointer to the - * related metaHeaders object. If the header name already exists in list, - * returns a pointer to the existing object. - */ - static MetaHeader::Pointer addMetaHeader(const String &header); + static Notes metaHeaders; ///< The list of configured meta headers typedef Vector ServiceConfigs; ServiceConfigs serviceConfigs; diff --git a/src/adaptation/History.h b/src/adaptation/History.h index d9c714fe4c..2067a7f709 100644 --- a/src/adaptation/History.h +++ b/src/adaptation/History.h @@ -4,6 +4,7 @@ #include "adaptation/DynamicGroupCfg.h" #include "Array.h" #include "HttpHeader.h" +#include "Notes.h" #include "RefCount.h" #include "SquidString.h" @@ -50,6 +51,9 @@ public: HttpHeader lastMeta; /// All REQMOD and RESPMOD meta headers merged. Last field wins conflicts. HttpHeader allMeta; + /// key:value pairs set by adaptation_meta, to be added to + /// AccessLogEntry::notes when ALE becomes available + NotePairs metaHeaders; /// sets future services for the Adaptation::AccessCheck to notice void setFutureServices(const DynamicGroupCfg &services); diff --git a/src/adaptation/ecap/XactionRep.cc b/src/adaptation/ecap/XactionRep.cc index 61473c9009..028a642404 100644 --- a/src/adaptation/ecap/XactionRep.cc +++ b/src/adaptation/ecap/XactionRep.cc @@ -177,9 +177,9 @@ Adaptation::Ecap::XactionRep::metaValue(const libecap::Name &name) const HttpReply *reply = dynamic_cast(theVirginRep.raw().header); if (name.known()) { // must check to avoid empty names matching unset cfg - typedef Adaptation::Config::MetaHeaders::iterator ACAMLI; + typedef Notes::iterator ACAMLI; for (ACAMLI i = Adaptation::Config::metaHeaders.begin(); i != Adaptation::Config::metaHeaders.end(); ++i) { - if (name == (*i)->name.termedBuf()) { + if (name == (*i)->key.termedBuf()) { if (const char *value = (*i)->match(request, reply)) return libecap::Area::FromTempString(value); else @@ -199,11 +199,11 @@ Adaptation::Ecap::XactionRep::visitEachMetaHeader(libecap::NamedValueVisitor &vi Must(request); HttpReply *reply = dynamic_cast(theVirginRep.raw().header); - typedef Adaptation::Config::MetaHeaders::iterator ACAMLI; + typedef Notes::iterator ACAMLI; for (ACAMLI i = Adaptation::Config::metaHeaders.begin(); i != Adaptation::Config::metaHeaders.end(); ++i) { const char *v = (*i)->match(request, reply); if (v) { - const libecap::Name name((*i)->name.termedBuf()); + const libecap::Name name((*i)->key.termedBuf()); const libecap::Area value = libecap::Area::FromTempString(v); visitor.visit(name, value); } @@ -218,13 +218,23 @@ Adaptation::Ecap::XactionRep::start() if (!theVirginRep.raw().body_pipe) makingVb = opNever; // there is nothing to deliver - const HttpRequest *request = dynamic_cast (theCauseRep ? + HttpRequest *request = dynamic_cast (theCauseRep ? theCauseRep->raw().header : theVirginRep.raw().header); Must(request); + + HttpReply *reply = dynamic_cast(theVirginRep.raw().header); + Adaptation::History::Pointer ah = request->adaptLogHistory(); if (ah != NULL) { // retrying=false because ecap never retries transactions adaptHistoryId = ah->recordXactStart(service().cfg().key, current_time, false); + typedef Notes::iterator ACAMLI; + for (ACAMLI i = Adaptation::Config::metaHeaders.begin(); i != Adaptation::Config::metaHeaders.end(); ++i) { + const char *v = (*i)->match(request, reply); + if (v && !ah->metaHeaders.hasByNameListMember((*i)->key.termedBuf(), v, ',')) { + ah->metaHeaders.addEntry(new HttpHeaderEntry(HDR_OTHER, (*i)->key.termedBuf(), v)); + } + } } theMaster->start(); diff --git a/src/adaptation/icap/ModXact.cc b/src/adaptation/icap/ModXact.cc index 9c83f912a2..a123754d12 100644 --- a/src/adaptation/icap/ModXact.cc +++ b/src/adaptation/icap/ModXact.cc @@ -1420,7 +1420,7 @@ void Adaptation::Icap::ModXact::makeRequestHeaders(MemBuf &buf) makeUsernameHeader(request, buf); // Adaptation::Config::metaHeaders - typedef Adaptation::Config::MetaHeaders::iterator ACAMLI; + typedef Notes::iterator ACAMLI; for (ACAMLI i = Adaptation::Config::metaHeaders.begin(); i != Adaptation::Config::metaHeaders.end(); ++i) { HttpRequest *r = virgin.cause ? virgin.cause : dynamic_cast(virgin.header); @@ -1428,8 +1428,12 @@ void Adaptation::Icap::ModXact::makeRequestHeaders(MemBuf &buf) HttpReply *reply = dynamic_cast(virgin.header); - if (const char *value = (*i)->match(r, reply)) - buf.Printf("%s: %s\r\n", (*i)->name.termedBuf(), value); + if (const char *value = (*i)->match(r, reply)) { + buf.Printf("%s: %s\r\n", (*i)->key.termedBuf(), value); + Adaptation::History::Pointer ah = request->adaptHistory(false); + if (ah != NULL && !ah->metaHeaders.hasByNameListMember((*i)->key.termedBuf(), value, ',')) + ah->metaHeaders.addEntry(new HttpHeaderEntry(HDR_OTHER, (*i)->key.termedBuf(), value)); + } } // fprintf(stderr, "%s\n", buf.content()); diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 58bab293b1..ed1f2192ce 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -134,9 +134,6 @@ static void parse_adaptation_service_set_type(); static void parse_adaptation_service_chain_type(); static void parse_adaptation_access_type(); -static void parse_adaptation_meta_type(Adaptation::Config::MetaHeaders *); -static void dump_adaptation_meta_type(StoreEntry *, const char *, Adaptation::Config::MetaHeaders &); -static void free_adaptation_meta_type(Adaptation::Config::MetaHeaders *); #endif #if ICAP_CLIENT @@ -219,6 +216,9 @@ static void parse_http_header_replace(HeaderManglers **manglers); static void dump_HeaderWithAclList(StoreEntry * entry, const char *name, HeaderWithAclList *headers); static void parse_HeaderWithAclList(HeaderWithAclList **header); static void free_HeaderWithAclList(HeaderWithAclList **header); +static void parse_note(Notes *); +static void dump_note(StoreEntry *, const char *, Notes &); +static void free_note(Notes *); static void parse_denyinfo(AclDenyInfoList ** var); static void dump_denyinfo(StoreEntry * entry, const char *name, AclDenyInfoList * var); static void free_denyinfo(AclDenyInfoList ** var); @@ -4211,24 +4211,6 @@ parse_adaptation_access_type() { Adaptation::Config::ParseAccess(LegacyParser); } - -static void -parse_adaptation_meta_type(Adaptation::Config::MetaHeaders *) -{ - Adaptation::Config::ParseMetaHeader(LegacyParser); -} - -static void -dump_adaptation_meta_type(StoreEntry *entry, const char *name, Adaptation::Config::MetaHeaders &) -{ - Adaptation::Config::DumpMetaHeader(entry, name); -} - -static void -free_adaptation_meta_type(Adaptation::Config::MetaHeaders *) -{ - // Nothing to do, it is released inside Adaptation::Config::freeService() -} #endif /* USE_ADAPTATION */ #if ICAP_CLIENT @@ -4660,3 +4642,19 @@ static void free_HeaderWithAclList(HeaderWithAclList **header) delete *header; *header = NULL; } + +static void parse_note(Notes *notes) +{ + assert(notes); + notes->parse(LegacyParser); +} + +static void dump_note(StoreEntry *entry, const char *name, Notes ¬es) +{ + notes.dump(entry, name); +} + +static void free_note(Notes *notes) +{ + notes->clean(); +} diff --git a/src/cf.data.depend b/src/cf.data.depend index 00d3f5a51c..ece4bf2651 100644 --- a/src/cf.data.depend +++ b/src/cf.data.depend @@ -35,7 +35,6 @@ HeaderWithAclList acl adaptation_access_type adaptation_service_set adaptation_service_chain acl icap_service icap_class adaptation_service_set_type icap_service ecap_service adaptation_service_chain_type icap_service ecap_service -adaptation_meta_type acl icap_access_type icap_class acl icap_class_type icap_service icap_service_type @@ -47,6 +46,7 @@ kb_size_t logformat YesNoNone memcachemode +note acl obsolete onoff peer diff --git a/src/cf.data.pre b/src/cf.data.pre index cd1119ed6b..a28c9d153f 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -3273,6 +3273,10 @@ DOC_START err_code The ID of an error response served by Squid or a similar internal error identifier. err_detail Additional err_code-dependent error information. + note The meta header specified by the argument. Also + logs the adaptation meta headers set by the + adaptation_meta configuration parameter. + If no argument given all meta headers logged. Connection related format codes: @@ -4921,6 +4925,22 @@ DOC_START only. DOC_END +NAME: note +TYPE: note +LOC: Config.notes +DEFAULT: none +DOC_START + This option used to log custom information about the master + transaction. For example, an admin may configure Squid to log + which "user group" the transaction belongs to, where "user group" + will be determined based on a set of ACLs and not [just] + authentication information. + Values of key/value pairs can be logged using %{key}note macros: + + note key value acl ... + logformat myFormat ... %{key}note ... +DOC_END + NAME: relaxed_header_parser COMMENT: on|off|warn TYPE: tristate @@ -7399,7 +7419,7 @@ adaptation_masterx_shared_names X-Subscriber-ID DOC_END NAME: adaptation_meta -TYPE: adaptation_meta_type +TYPE: note IFDEF: USE_ADAPTATION LOC: Adaptation::Config::metaHeaders DEFAULT: none @@ -7431,6 +7451,12 @@ DOC_START any character, which is currently only useful for escaping backslashes and double quotes. For example, "this string has one backslash (\\) and two \"quotes\"" + + Used adaptation_meta header values may be logged via %note + logformat code. If multiple adaptation_meta headers with the same name + are used during master transaction lifetime, the header values are + logged in the order they were used and duplicate values are ignored + (only the first repeated value will be logged). DOC_END NAME: icap_retry diff --git a/src/client_side.cc b/src/client_side.cc index 2973d3a6f9..d3d8d7ff44 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -598,6 +598,7 @@ prepareLogWithRequestDetails(HttpRequest * request, AccessLogEntry::Pointer &aLo packerToMemInit(&p, &mb); ah->lastMeta.packInto(&p); aLogEntry->adapt.last_meta = xstrdup(mb.buf); + aLogEntry->notes.append(&ah->metaHeaders); } #endif @@ -693,6 +694,15 @@ ClientHttpRequest::logRequest() #endif + /*Add meta headers*/ + typedef Notes::iterator ACAMLI; + for (ACAMLI i = Config.notes.begin(); i != Config.notes.end(); ++i) { + if (const char *value = (*i)->match(request, al->reply)) { + al->notes.addEntry(new HttpHeaderEntry(HDR_OTHER, (*i)->key.termedBuf(), value)); + debugs(33, 3, HERE << (*i)->key.termedBuf() << " " << value); + } + } + ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.log, this); if (al->reply) diff --git a/src/format/ByteCode.h b/src/format/ByteCode.h index ef25149429..b1c3694709 100644 --- a/src/format/ByteCode.h +++ b/src/format/ByteCode.h @@ -196,6 +196,7 @@ typedef enum { LFT_SSL_USER_CERT_ISSUER, #endif + LFT_NOTE, LFT_PERCENT /* special string cases for escaped chars */ } ByteCode_t; diff --git a/src/format/Format.cc b/src/format/Format.cc index 260c02fdae..d98bc76b68 100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@ -1040,6 +1040,23 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS } break; #endif + case LFT_NOTE: + if (fmt->data.string) { + sb = al->notes.getByName(fmt->data.string); + out = sb.termedBuf(); + quote = 1; + } else { + HttpHeaderPos pos = HttpHeaderInitPos; + while (const HttpHeaderEntry *e = al->notes.getEntry(&pos)) { + sb.append(e->name); + sb.append(": "); + sb.append(e->value); + sb.append("\r\n"); + } + out = sb.termedBuf(); + quote = 1; + } + break; case LFT_PERCENT: out = "%"; diff --git a/src/format/Token.cc b/src/format/Token.cc index 099dcbeeba..7c24bb0ce0 100644 --- a/src/format/Token.cc +++ b/src/format/Token.cc @@ -150,6 +150,7 @@ static TokenTableEntry TokenTableMisc[] = { {">eui", LFT_CLIENT_EUI}, {"err_code", LFT_SQUID_ERROR }, {"err_detail", LFT_SQUID_ERROR_DETAIL }, + {"note", LFT_NOTE }, {NULL, LFT_NONE} /* this must be last */ }; diff --git a/src/log/access_log.cc b/src/log/access_log.cc index 84d7c06d87..fdfcfc939b 100644 --- a/src/log/access_log.cc +++ b/src/log/access_log.cc @@ -33,7 +33,11 @@ #include "squid.h" #include "AccessLogEntry.h" #include "acl/Checklist.h" +#if USE_ADAPTATION +#include "adaptation/Config.h" +#endif #include "CachePeer.h" +#include "errorpage.h" #include "err_detail_type.h" #include "errorpage.h" #include "errorpage.h" @@ -326,7 +330,8 @@ accessLogInit(void) curr_token->type == Format::LFT_ADAPTATION_ALL_XACT_TIMES || curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER || curr_token->type == Format::LFT_ADAPTATION_LAST_HEADER_ELEM || - curr_token->type == Format::LFT_ADAPTATION_LAST_ALL_HEADERS) { + curr_token->type == Format::LFT_ADAPTATION_LAST_ALL_HEADERS|| + (curr_token->type == Format::LFT_NOTE && !Adaptation::Config::metaHeaders.empty())) { Log::TheConfig.hasAdaptToken = true; } #if ICAP_CLIENT diff --git a/src/tests/stub_cache_cf.cc b/src/tests/stub_cache_cf.cc index f46821d69e..9bc906a2a9 100644 --- a/src/tests/stub_cache_cf.cc +++ b/src/tests/stub_cache_cf.cc @@ -48,5 +48,7 @@ void requirePathnameExists(const char *name, const char *path) STUB_NOP void parse_time_t(time_t * var) STUB char * strtokFile(void) STUB_RETVAL(NULL) void ConfigParser::ParseUShort(unsigned short *var) STUB +void ConfigParser::ParseString(String*) STUB void dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) STUB +void dump_acl_list(StoreEntry*, ACLList*) STUB YesNoNone::operator void*() const { STUB_NOP; return NULL; } diff --git a/src/tests/testHttpReply.cc b/src/tests/testHttpReply.cc index e393898de8..73133cf697 100644 --- a/src/tests/testHttpReply.cc +++ b/src/tests/testHttpReply.cc @@ -23,12 +23,6 @@ MemObject::endOffset() const } #include "ConfigParser.h" -void -ConfigParser::destruct() -{ -// CALLED as shutdown no-op -// fatal("ConfigParser::destruct. Not implemented."); -} void eventAdd(const char *name, EVH * func, void *arg, double when, int, bool cbdata)