]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
note option
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 26 Oct 2012 19:42:31 +0000 (22:42 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 26 Oct 2012 19:42:31 +0000 (22:42 +0300)
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

20 files changed:
src/AccessLogEntry.h
src/HttpHeader.h
src/HttpHeaderTools.cc
src/Makefile.am
src/SquidConfig.h
src/adaptation/Config.cc
src/adaptation/Config.h
src/adaptation/History.h
src/adaptation/ecap/XactionRep.cc
src/adaptation/icap/ModXact.cc
src/cache_cf.cc
src/cf.data.depend
src/cf.data.pre
src/client_side.cc
src/format/ByteCode.h
src/format/Format.cc
src/format/Token.cc
src/log/access_log.cc
src/tests/stub_cache_cf.cc
src/tests/testHttpReply.cc

index eb011e8ea0c2ba26aa1a083c3ed173e0af1d586b..8ed08f930c2533cca608bffc52e9243147881b12 100644 (file)
@@ -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
index fc76880cdf9dda95e0cae62e933d47cf74d4ddd5..4def174193ed30aa6fa3185a201739570a5a765e 100644 (file)
@@ -175,6 +175,7 @@ typedef enum {
 #if USE_SSL
     hoErrorDetail,
 #endif
+    hoNote,
     hoEnd
 } http_hdr_owner_type;
 
index a49091bb527389f027b1644280243cc472f49f2f..588f1c6902ef2ef76a44bd83908b6bde96e04901 100644 (file)
  */
 
 #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"
index 7a6b3d016456f0e9c20aec8a2240309c917e21a0..f908ed2394ee1d9e4873f5560448354d3af86c1d 100644 (file)
@@ -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 \
index 746f697bee7b3846ec1074b237ff93baa16f141f..40a8a235f85d5a87f87f1352f4a08b95a15f5809 100644 (file)
@@ -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
index 0d3b86940f82c895c4e973cca81536bafe3e6536..5d233593d04cf55b028c1abe3624624d0cf9835c 100644 (file)
@@ -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()
 {
index da3234b7a5fc060db052af32a4d3b6dd88110167..65061a325c077d1e983a26e7b3682fa8bba09e87 100644 (file)
@@ -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<MetaHeader> Pointer;
-        /// Stores a value for the meta header.
-        class Value: public RefCountable
-        {
-        public:
-            typedef RefCount<Value> 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<Value::Pointer> 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<MetaHeader::Pointer> 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<ServiceConfigPointer> ServiceConfigs;
     ServiceConfigs serviceConfigs;
index d9c714fe4c1848cd9abbe7edd6017ff50a74f3a2..2067a7f709f2e83d73f5c1d0b6b27f043abb7c8a 100644 (file)
@@ -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);
index 61473c9009b4b1556da5e9b8674a8e312f4aa186..028a642404c97ed787b848dc2339fe88d5c68ab4 100644 (file)
@@ -177,9 +177,9 @@ Adaptation::Ecap::XactionRep::metaValue(const libecap::Name &name) const
     HttpReply *reply = dynamic_cast<HttpReply*>(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<HttpReply*>(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<const HttpRequest*> (theCauseRep ?
+    HttpRequest *request = dynamic_cast<HttpRequest*> (theCauseRep ?
                                  theCauseRep->raw().header : theVirginRep.raw().header);
     Must(request);
+
+    HttpReply *reply = dynamic_cast<HttpReply*>(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();
index 9c83f912a202b8ef5f8a9a62e38cbdf57bd00916..a123754d12b650c5ca7fb1783a7b8295ad3c4e1e 100644 (file)
@@ -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<HttpRequest*>(virgin.header);
@@ -1428,8 +1428,12 @@ void Adaptation::Icap::ModXact::makeRequestHeaders(MemBuf &buf)
 
         HttpReply *reply = dynamic_cast<HttpReply*>(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());
index 58bab293b171d85315ec4275f968c96b1b6a1396..ed1f2192cecb62ee0a1ac700fdffceae99fe4b28 100644 (file)
 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 &notes)
+{
+    notes.dump(entry, name);
+}
+
+static void free_note(Notes *notes)
+{
+    notes->clean();
+}
index 00d3f5a51c4a9744e967f6c903eff079a1ce71fc..ece4bf2651746e3b64b9097798aeb8889aa623fa 100644 (file)
@@ -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
index cd1119ed6b9fea8aabafbd8699e5900516961647..a28c9d153f1917b14c3859fa4e90b7ab1dc863a5 100644 (file)
@@ -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
index 2973d3a6f9b0230ce6974ff359f33b3ffdaec4e4..d3d8d7ff44e5c5a9d0a3538ec0c63e0d192ed4c2 100644 (file)
@@ -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)
index ef251494295886cded411712eb45b78fcbd5425e..b1c369470969f0cb4dc03433c243f79d7b99d4ad 100644 (file)
@@ -196,6 +196,7 @@ typedef enum {
     LFT_SSL_USER_CERT_ISSUER,
 #endif
 
+    LFT_NOTE,
     LFT_PERCENT                        /* special string cases for escaped chars */
 } ByteCode_t;
 
index 260c02fdae2aecac55377d8a22b91608118a4743..d98bc76b681a55d38654356d64dc0fd079a41896 100644 (file)
@@ -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 = "%";
index 099dcbeeba131f452fe25d6281f05d650e93e550..7c24bb0ce0a6136e7b489178c1cf6630df60ae84 100644 (file)
@@ -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 */
 };
 
index 84d7c06d87a834e14ada1882dfe5fdb3fa19fa59..fdfcfc939bc112c4d5c86c4aced342ec9c275935 100644 (file)
 #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
index f46821d69ed58760cac4d51f99fabca18680f5f7..9bc906a2a9464338aca6cc018e80c20759af0e35 100644 (file)
@@ -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; }
index e393898de86059294c0add26a1b8cf9d2fa6358c..73133cf6970165a27c1b1f521239f621c3bbcba8 100644 (file)
@@ -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)