Add url_rewrite_extras for redirector helpers The url_rewrite_extras is a "quoted string" with logformat %macro support. It is appended to request line for redirector helpers. Example usage: url_rewrite_extras "Note1=%{Note1}note Note2=%{Note2}note" This is a Measurement Factory project. === modified file 'src/SquidConfig.h' --- src/SquidConfig.h 2014-01-12 17:51:12 +0000 +++ src/SquidConfig.h 2014-02-20 17:59:54 +0000 @@ -523,40 +523,42 @@ char *flags; acl_access *cert_error; SSL_CTX *sslContext; sslproxy_cert_sign *cert_sign; sslproxy_cert_adapt *cert_adapt; } ssl_client; #endif char *accept_filter; int umask; int max_filedescriptors; int workers; CpuAffinityMap *cpuAffinityMap; #if USE_LOADABLE_MODULES wordlist *loadable_module_names; #endif int client_ip_max_connections; + char *redirector_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. } dns; }; extern SquidConfig Config; class SquidConfig2 { public: struct { int enable_purge; int mangle_request_headers; } onoff; uid_t effectiveUserID; gid_t effectiveGroupID; }; === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2014-02-10 09:59:19 +0000 +++ src/cache_cf.cc 2014-02-23 20:44:06 +0000 @@ -3020,40 +3020,55 @@ if (!token) { self_destruct(); return; } while (*token && xisspace(*token)) ++token; if (!*token) { self_destruct(); return; } *var = xstrdup((char *) token); } #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) { storeAppendPrintf(entry, "%s %d seconds\n", name, (int) var); } void parse_time_t(time_t * var) { time_msec_t tval; parseTimeLine(&tval, T_SECOND_STR, false); *var = static_cast(tval/1000); } static void free_time_t(time_t * var) { *var = 0; } static void === modified file 'src/cf.data.depend' --- src/cf.data.depend 2013-08-29 09:21:53 +0000 +++ src/cf.data.depend 2014-02-23 20:44:21 +0000 @@ -38,39 +38,40 @@ adaptation_service_chain_type icap_service ecap_service icap_access_type icap_class acl icap_class_type icap_service icap_service_type icap_service_failure_limit ecap_service_type int kb_int64_t kb_size_t logformat YesNoNone memcachemode note acl obsolete onoff peer peer_access cache_peer acl pipelinePrefetch PortCfg QosConfig +TokenOrQuotedString refreshpattern removalpolicy size_t IpAddress_list string string time_msec time_t tristate uri_whitespace u_short wccp2_method wccp2_amethod wccp2_service wccp2_service_info wordlist sslproxy_ssl_bump acl sslproxy_cert_sign acl sslproxy_cert_adapt acl === modified file 'src/cf.data.pre' --- src/cf.data.pre 2014-01-30 21:24:44 +0000 +++ src/cf.data.pre 2014-02-23 20:44:32 +0000 @@ -4738,40 +4738,52 @@ This clause supports both fast and slow acl types. See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details. DOC_END NAME: url_rewrite_bypass redirector_bypass TYPE: onoff LOC: Config.onoff.redirector_bypass DEFAULT: off DOC_START When this is 'on', a request will not go through the redirector if all the helpers are busy. If this is 'off' and the redirector queue grows too large, Squid will exit with a FATAL error and ask you to increase the number of redirectors. You should only enable this if the redirectors are not critical to your caching system. If you use redirectors for access control, and you enable this option, users may have access to pages they should not be allowed to request. DOC_END +NAME: url_rewrite_extras format +TYPE: TokenOrQuotedString +LOC: Config.redirector_extras +DEFAULT: none +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 ----------------------------------------------------------------------------- COMMENT_END NAME: store_id_program storeurl_rewrite_program TYPE: wordlist LOC: Config.Program.store_id DEFAULT: none DOC_START Specify the location of the executable StoreID helper to use. Since they can perform almost any function there isn't one included. For each requested URL, the helper will receive one line with the format [channel-ID ] URL client_ip "/" fqdn user method [ kv-pairs] After processing the request the helper must reply using the following format: === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2013-12-06 23:52:26 +0000 +++ src/client_side_request.cc 2014-02-21 17:07:39 +0000 @@ -879,41 +879,41 @@ static void clientRedirectAccessCheckDone(allow_t answer, void *data) { ClientRequestContext *context = (ClientRequestContext *)data; ClientHttpRequest *http = context->http; context->acl_checklist = NULL; if (answer == ACCESS_ALLOWED) redirectStart(http, clientRedirectDoneWrapper, context); else { HelperReply nilReply; nilReply.result = HelperReply::Error; context->clientRedirectDone(nilReply); } } 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); } else redirectStart(http, clientRedirectDoneWrapper, this); } /** * This methods handles Access checks result of StoreId access list. * Will handle as "ERR" (no change) in a case Access is not allowed. */ static void clientStoreIdAccessCheckDone(allow_t answer, void *data) { ClientRequestContext *context = static_cast(data); ClientHttpRequest *http = context->http; context->acl_checklist = NULL; if (answer == ACCESS_ALLOWED) storeIdStart(http, clientStoreIdDoneWrapper, context); === modified file 'src/redirect.cc' --- src/redirect.cc 2013-11-23 00:58:42 +0000 +++ src/redirect.cc 2014-02-21 15:49:59 +0000 @@ -21,40 +21,41 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "squid.h" #include "acl/Checklist.h" #include "client_side.h" #include "client_side_reply.h" #include "client_side_request.h" #include "comm/Connection.h" #include "fde.h" #include "fqdncache.h" +#include "format/Format.h" #include "globals.h" #include "HttpRequest.h" #include "mgr/Registration.h" #include "redirect.h" #include "rfc1738.h" #include "SBuf.h" #include "SquidConfig.h" #include "Store.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #if USE_SSL #include "ssl/support.h" #endif /// url maximum lengh + extra informations passed to redirector #define MAX_REDIRECTOR_REQUEST_STRLEN (MAX_URL + 1024) class RedirectStateData { @@ -65,40 +66,41 @@ void *data; SBuf orig_url; Ip::Address client_addr; const char *client_ident; const char *method_s; HLPCB *handler; private: CBDATA_CLASS2(RedirectStateData); }; static HLPCB redirectHandleReply; static HLPCB storeIdHandleReply; static helper *redirectors = NULL; static helper *storeIds = NULL; static OBJH redirectStats; static OBJH storeIdStats; static int redirectorBypassed = 0; static int storeIdBypassed = 0; +static Format::Format *redirectorExtrasFmt = NULL; CBDATA_CLASS_INIT(RedirectStateData); RedirectStateData::RedirectStateData(const char *url) : data(NULL), orig_url(url), client_addr(), client_ident(NULL), method_s(NULL), handler(NULL) { } RedirectStateData::~RedirectStateData() { } static void redirectHandleReply(void *data, const HelperReply &reply) { @@ -272,48 +274,54 @@ #if USE_SSL if (!r->client_ident && conn != NULL && Comm::IsConnOpen(conn->clientConnection)) { r->client_ident = sslGetUserEmail(fd_table[conn->clientConnection->fd].ssl); debugs(61, 5, HERE << "ssl-user=" << (r->client_ident?r->client_ident:"NULL")); } #endif if (!r->client_ident) r->client_ident = dash_str; r->method_s = RequestMethodStr(http->request->method); r->handler = handler; r->data = cbdataReference(data); 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(); + redirectorExtrasFmt->assemble(requestExtras, http->al, 0); + + sz = snprintf(buf, MAX_REDIRECTOR_REQUEST_STRLEN, "%s %s/%s %s %s myip=%s myport=%d%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()); + http->request->my_addr.port(), + requestExtras.hasContent() ? " " : "", + requestExtras.hasContent() ? requestExtras.content() : ""); if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) { if (sz<=0) { status = Http::scInternalServerError; debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to " << name << ". Request ABORTED."); } else { status = Http::scRequestUriTooLarge; debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to " << name << " exceeds MAX_REDIRECTOR_REQUEST_STRLEN (" << MAX_REDIRECTOR_REQUEST_STRLEN << "). Request ABORTED."); } clientStreamNode *node = (clientStreamNode *)http->client_stream.tail->prev->data; clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); Ip::Address tmpnoaddr; tmpnoaddr.setNoAddr(); repContext->setReplyToError(ERR_GATEWAY_FAILURE, status, http->request->method, NULL, http->getConn() != NULL && http->getConn()->clientConnection != NULL ? http->getConn()->clientConnection->remote : tmpnoaddr, http->request, @@ -403,49 +411,56 @@ redirectors->ipc_type = IPC_STREAM; helperOpenServers(redirectors); } if (Config.Program.store_id) { if (storeIds == NULL) storeIds = new helper("store_id"); storeIds->cmdline = Config.Program.store_id; storeIds->childs.updateLimits(Config.storeIdChildren); storeIds->ipc_type = IPC_STREAM; helperOpenServers(storeIds); } + if (Config.redirector_extras) { + redirectorExtrasFmt = new ::Format::Format("redirecor_extras"); + (void)redirectorExtrasFmt->parse(Config.redirector_extras); + } + init = true; } void redirectShutdown(void) { /** FIXME: Temporary unified helpers Shutdown * When and if needed for more helpers a separated shutdown * method will be added for each of them. */ if (!storeIds && !redirectors) return; if (redirectors) helperShutdown(redirectors); if (storeIds) helperShutdown(storeIds); if (!shutting_down) return; delete redirectors; redirectors = NULL; delete storeIds; storeIds = NULL; + delete redirectorExtrasFmt; + redirectorExtrasFmt = NULL; }