From: Christos Tsantilas Date: Wed, 12 Mar 2014 16:46:27 +0000 (+0200) Subject: Add url_rewrite_extras and store_id_extras for redirector and store_id helpers X-Git-Tag: SQUID_3_5_0_1~337 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b11724b;p=thirdparty%2Fsquid.git Add url_rewrite_extras and store_id_extras for redirector and store_id helpers The url_rewrite_extras/store_id_extras is a "quoted string" with logformat %macro support. It is used to modify the request line for redirector and storeId helpers. The url rewrite and store_id helpers request format now is: url [ extras] and the default value for extras is: "%>a/%>A %un %>rm myip=%la myport=%lp" Example usage: url_rewrite_extras "Note1=%{Note1}note Note2=%{Note2}note" This is a Measurement Factory project. --- diff --git a/src/SquidConfig.h b/src/SquidConfig.h index 013ae21741..aa92d38254 100644 --- a/src/SquidConfig.h +++ b/src/SquidConfig.h @@ -540,6 +540,10 @@ public: int client_ip_max_connections; + char *redirector_extras; + + char *storeId_extras; + struct { int v4_first; ///< Place IPv4 first in the order of DNS results. ssize_t packet_max; ///< maximum size EDNS advertised for DNS replies. diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 0b537d3445..caf65c1ad4 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -3032,6 +3032,21 @@ parse_eol(char *volatile *var) #define dump_eol dump_string #define free_eol free_string +static void +parse_TokenOrQuotedString(char **var) +{ + char *token = ConfigParser::NextQuotedToken(); + safe_free(*var); + + if (token == NULL) + self_destruct(); + + *var = xstrdup(token); +} + +#define dump_TokenOrQuotedString dump_string +#define free_TokenOrQuotedString free_string + static void dump_time_t(StoreEntry * entry, const char *name, time_t var) { diff --git a/src/cf.data.depend b/src/cf.data.depend index 1013873910..cfd5400c87 100644 --- a/src/cf.data.depend +++ b/src/cf.data.depend @@ -55,6 +55,7 @@ peer_access cache_peer acl pipelinePrefetch PortCfg QosConfig +TokenOrQuotedString refreshpattern removalpolicy size_t diff --git a/src/cf.data.pre b/src/cf.data.pre index 829c22d2e2..2a8ef198a8 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -4607,7 +4607,7 @@ DOC_START For each requested URL, the rewriter will receive on line with the format - [channel-ID ] URL client_ip "/" fqdn user method [ kv-pairs] + [channel-ID ] URL [ extras] After processing the request the helper must reply using the following format: @@ -4755,6 +4755,18 @@ DOC_START be allowed to request. DOC_END +NAME: url_rewrite_extras format +TYPE: TokenOrQuotedString +LOC: Config.redirector_extras +DEFAULT: "%>a/%>A %un %>rm myip=%la myport=%lp" +DOC_START + Specifies a string to be append to request line format for the + rewriter helper. "Quoted" format values may contain spaces and + logformat %macros. In theory, any logformat %macro can be used. + In practice, a %macro expands as a dash (-) if the helper request is + sent before the required macro information is available to Squid. +DOC_END + COMMENT_START OPTIONS FOR STORE ID ----------------------------------------------------------------------------- @@ -4770,7 +4782,7 @@ DOC_START For each requested URL, the helper will receive one line with the format - [channel-ID ] URL client_ip "/" fqdn user method [ kv-pairs] + [channel-ID ] URL [ extras] After processing the request the helper must reply using the following format: @@ -4790,8 +4802,8 @@ DOC_START a result being identified. - Helper programs should be prepared to receive and possibly ignore additional - kv-pairs with keys they do not support. + Helper programs should be prepared to receive and possibly ignore + additional whitespace-separated tokens on each input line. When using the concurrency= option the protocol is changed by introducing a query channel tag in front of the request/response. @@ -4808,6 +4820,18 @@ DOC_START By default, a StoreID helper is not used. DOC_END +NAME: store_id_extras format +TYPE: TokenOrQuotedString +LOC: Config.storeId_extras +DEFAULT: "%>a/%>A %un %>rm myip=%la myport=%lp" +DOC_START + Specifies a string to be append to request line format for the + StoreId helper. "Quoted" format values may contain spaces and + logformat %macros. In theory, any logformat %macro can be used. + In practice, a %macro expands as a dash (-) if the helper request is + sent before the required macro information is available to Squid. +DOC_END + NAME: store_id_children storeurl_rewrite_children TYPE: HelperChildConfig DEFAULT: 20 startup=0 idle=1 concurrency=0 diff --git a/src/cf_gen.cc b/src/cf_gen.cc index 246b3d9405..cdb3c38b4f 100644 --- a/src/cf_gen.cc +++ b/src/cf_gen.cc @@ -158,6 +158,7 @@ static void gen_default_if_none(const EntryList &, std::ostream&); static void gen_default_postscriptum(const EntryList &, std::ostream&); static bool isDefined(const std::string &name); static const char *available_if(const std::string &name); +static const char *gen_quote_escape(const std::string &var); static void checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries) @@ -540,7 +541,7 @@ gen_default(const EntryList &head, std::ostream &fout) fout << "#if " << entry->ifdef << std::endl; for (LineList::const_iterator l = entry->defaults.preset.begin(); l != entry->defaults.preset.end(); ++l) { - fout << " default_line(\"" << entry->name << " " << *l << "\");" << std::endl; + fout << " default_line(\"" << entry->name << " " << gen_quote_escape(*l) << "\");" << std::endl; } if (entry->ifdef.size()) @@ -581,7 +582,7 @@ gen_default_if_none(const EntryList &head, std::ostream &fout) fout << " if (check_null_" << entry->type << "(" << entry->loc << ")) {" << std::endl; for (LineList::const_iterator l = entry->defaults.if_none.begin(); l != entry->defaults.if_none.end(); ++l) - fout << " default_line(\"" << entry->name << " " << *l <<"\");" << std::endl; + fout << " default_line(\"" << entry->name << " " << gen_quote_escape(*l) <<"\");" << std::endl; fout << " }" << std::endl; if (entry->ifdef.size()) @@ -822,13 +823,13 @@ gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output) if (entry->defaults.preset.size() && entry->defaults.preset.front().compare("none") != 0) { // Display DEFAULT: line(s) for (LineList::const_iterator l = entry->defaults.preset.begin(); l != entry->defaults.preset.end(); ++l) { - snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), l->c_str()); + snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), gen_quote_escape(*l)); def.push_back(buf); } } else if (entry->defaults.if_none.size()) { // Display DEFAULT_IF_NONE: line(s) for (LineList::const_iterator l = entry->defaults.if_none.begin(); l != entry->defaults.if_none.end(); ++l) { - snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), l->c_str()); + snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), gen_quote_escape(*l)); def.push_back(buf); } } @@ -864,3 +865,22 @@ gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output) } } } + +static const char * +gen_quote_escape(const std::string &var) +{ + static std::string esc; + esc.clear(); + + for (int i = 0; i < var.length(); ++i) { + switch (var[i]) { + case '"': + case '\\': + esc += '\\'; + default: + esc += var[i]; + } + } + + return esc.c_str(); +} diff --git a/src/client_side_request.cc b/src/client_side_request.cc index 06c8685047..b2f2beb8f2 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -897,7 +897,7 @@ void ClientRequestContext::clientRedirectStart() { debugs(33, 5, HERE << "'" << http->uri << "'"); - + (void)SyncNotes(*http->al, *http->request); if (Config.accessList.redirector) { acl_checklist = clientAclChecklistCreate(Config.accessList.redirector, http); acl_checklist->nonBlockingCheck(clientRedirectAccessCheckDone, this); diff --git a/src/redirect.cc b/src/redirect.cc index 4131d1c3ad..1ebd680d44 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -38,6 +38,7 @@ #include "comm/Connection.h" #include "fde.h" #include "fqdncache.h" +#include "format/Format.h" #include "globals.h" #include "HttpRequest.h" #include "mgr/Registration.h" @@ -82,6 +83,8 @@ static OBJH redirectStats; static OBJH storeIdStats; static int redirectorBypassed = 0; static int storeIdBypassed = 0; +static Format::Format *redirectorExtrasFmt = NULL; +static Format::Format *storeIdExtrasFmt = NULL; CBDATA_CLASS_INIT(RedirectStateData); @@ -233,15 +236,13 @@ storeIdStats(StoreEntry * sentry) } static void -constructHelperQuery(const char *name, helper *hlp, HLPCB *replyHandler, ClientHttpRequest * http, HLPCB *handler, void *data) +constructHelperQuery(const char *name, helper *hlp, HLPCB *replyHandler, ClientHttpRequest * http, HLPCB *handler, void *data, Format::Format *requestExtrasFmt) { ConnStateData * conn = http->getConn(); const char *fqdn; char buf[MAX_REDIRECTOR_REQUEST_STRLEN]; int sz; Http::StatusCode status; - char claddr[MAX_IPSTRLEN]; - char myaddr[MAX_IPSTRLEN]; /** TODO: create a standalone method to initialize * the RedirectStateData for all the helpers. @@ -289,14 +290,15 @@ constructHelperQuery(const char *name, helper *hlp, HLPCB *replyHandler, ClientH if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL) fqdn = dash_str; - sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d\n", + static MemBuf requestExtras; + requestExtras.reset(); + if (requestExtrasFmt) + requestExtrasFmt->assemble(requestExtras, http->al, 0); + + sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s%s%s\n", r->orig_url.c_str(), - r->client_addr.toStr(claddr,MAX_IPSTRLEN), - fqdn, - r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str, - r->method_s, - http->request->my_addr.toStr(myaddr,MAX_IPSTRLEN), - http->request->my_addr.port()); + requestExtras.hasContent() ? " " : "", + requestExtras.hasContent() ? requestExtras.content() : ""); if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) { if (sz<=0) { @@ -353,7 +355,7 @@ redirectStart(ClientHttpRequest * http, HLPCB * handler, void *data) return; } - constructHelperQuery("redirector", redirectors, redirectHandleReply, http, handler, data); + constructHelperQuery("redirector", redirectors, redirectHandleReply, http, handler, data, redirectorExtrasFmt); } /** @@ -379,7 +381,7 @@ storeIdStart(ClientHttpRequest * http, HLPCB * handler, void *data) return; } - constructHelperQuery("storeId helper", storeIds, storeIdHandleReply, http, handler, data); + constructHelperQuery("storeId helper", storeIds, storeIdHandleReply, http, handler, data, storeIdExtrasFmt); } void @@ -420,6 +422,16 @@ redirectInit(void) helperOpenServers(storeIds); } + if (Config.redirector_extras) { + redirectorExtrasFmt = new ::Format::Format("redirecor_extras"); + (void)redirectorExtrasFmt->parse(Config.redirector_extras); + } + + if (Config.storeId_extras) { + storeIdExtrasFmt = new ::Format::Format("storeId_extras"); + (void)storeIdExtrasFmt->parse(Config.storeId_extras); + } + init = true; } @@ -448,4 +460,9 @@ redirectShutdown(void) delete storeIds; storeIds = NULL; + delete redirectorExtrasFmt; + redirectorExtrasFmt = NULL; + + delete storeIdExtrasFmt; + storeIdExtrasFmt = NULL; }