Bug 3349: Bad support for adaptation service URIs with '=' Currently using URIs which include "=" is not supported by ecap_service/icap_service configuration parameters. Also the squid.conf documentation about ecap_service is outdated. This patch - Fixes the [e|i]cap_service line parser to allow URIs with "=" - Changes the [e|i]cap_service configuration parameter to use the following syntax: ecap_service id vectoring_point uri [name=value ...] - Check for duplicated options - Fixes the related documentation - Also the older [e|i]cap_service syntax forms are supported: ecap_service id vectoring_point [1|0] uri ecap_service id vectoring_point [name=value ...] uri - The "uri" options is not documented but supported. This is a Measurement Factory project. === modified file 'src/adaptation/ServiceConfig.cc' --- src/adaptation/ServiceConfig.cc 2011-05-24 22:26:21 +0000 +++ src/adaptation/ServiceConfig.cc 2011-10-05 08:30:22 +0000 @@ -6,6 +6,7 @@ #include "ConfigParser.h" #include "adaptation/ServiceConfig.h" #include "ip/tools.h" +#include Adaptation::ServiceConfig::ServiceConfig(): port(-1), method(methodNone), point(pointNone), @@ -69,29 +70,39 @@ bypass = routing = false; // handle optional service name=value parameters - const char *lastOption = NULL; bool grokkedUri = false; bool onOverloadSet = false; + std::set options; + while (char *option = strtok(NULL, w_space)) { + const char *name = option; + const char *value = ""; if (strcmp(option, "0") == 0) { // backward compatibility - bypass = false; - continue; - } - if (strcmp(option, "1") == 0) { // backward compatibility - bypass = true; - continue; - } - - const char *name = option; - char *value = strstr(option, "="); - if (!value) { - lastOption = option; - break; - } - *value = '\0'; // terminate option name - ++value; // skip '=' - - // TODO: warn if option is set twice? + name = "bypass"; + value = "off"; + } else if (strcmp(option, "1") == 0) { // backward compatibility + name = "bypass"; + value = "on"; + } else { + char *eq = strstr(option, "="); + const char *sffx = strstr(option, "://"); + if (!eq || (sffx && sffx < eq)) { //no "=" or has the form "icap://host?arg=val" + name = "uri"; + value = option; + } else { // a normal name=value option + *eq = '\0'; // terminate option name + value = eq + 1; // skip '=' + } + } + + // Check if option is set twice + if (options.find(name) != options.end()) { + debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << + "Douplicate option \"" << name << "\" in ataptation service definition"); + return false; + } + options.insert(name); + bool grokked = false; if (strcmp(name, "bypass") == 0) { grokked = grokBool(bypass, name, value); @@ -119,14 +130,10 @@ if (!onOverloadSet) onOverload = bypass ? srvBypass : srvWait; - // what is left must be the service URI - if (!grokkedUri && !grokUri(lastOption)) - return false; - - // there should be nothing else left - if (const char *tail = strtok(NULL, w_space)) { - debugs(3, 0, cfg_filename << ':' << config_lineno << ": " << - "garbage after adaptation service URI: " << tail); + // is the service URI set? + if (!grokkedUri) { + debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " << + "No \"uri\" option in adaptation service definition"); return false; } === modified file 'src/cf.data.pre' --- src/cf.data.pre 2011-09-22 00:46:26 +0000 +++ src/cf.data.pre 2011-10-05 08:29:23 +0000 @@ -6596,17 +6596,19 @@ DOC_START Defines a single ICAP service using the following format: - icap_service service_name vectoring_point [options] service_url + icap_service id vectoring_point uri [option ...] - service_name: ID - an opaque identifier which must be unique in squid.conf + id: ID + an opaque identifier or name which is used to direct traffic to + this specific service. Must be unique among all adaptation + services in squid.conf. vectoring_point: reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache This specifies at which point of transaction processing the ICAP service should be activated. *_postcache vectoring points are not yet supported. - service_url: icap://servername:port/servicepath + uri: icap://servername:port/servicepath ICAP server and service location. ICAP does not allow a single service to handle both REQMOD and RESPMOD @@ -6675,8 +6677,8 @@ deprecated but supported for backward compatibility. Example: -icap_service svcBlocker reqmod_precache bypass=0 icap://icap1.mydomain.net:1344/reqmod -icap_service svcLogger reqmod_precache routing=on icap://icap2.mydomain.net:1344/respmod +icap_service svcBlocker reqmod_precache icap://icap1.mydomain.net:1344/reqmod bypass=0 +icap_service svcLogger reqmod_precache icap://icap2.mydomain.net:1344/respmod routing=on DOC_END NAME: icap_class @@ -6728,25 +6730,56 @@ DOC_START Defines a single eCAP service - ecap_service servicename vectoring_point bypass service_url - - vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache + ecap_service id vectoring_point uri [option ...] + + id: ID + an opaque identifier or name which is used to direct traffic to + this specific service. Must be unique among all adaptation + services in squid.conf. + + vectoring_point: reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache This specifies at which point of transaction processing the eCAP service should be activated. *_postcache vectoring points are not yet supported. - bypass = 1|0 - If set to 1, the eCAP service is treated as optional. If the - service cannot be reached or malfunctions, Squid will try to - ignore any errors and process the message as if the service + + uri: ecap://vendor/service_name?custom&cgi=style¶meters=optional + Squid uses the eCAP service URI to match this configuration + line with one of the dynamically loaded services. Each loaded + eCAP service must have a unique URI. Obtain the right URI from + the service provider. + + + Service options are separated by white space. eCAP services support + the following name=value options: + + bypass=on|off|1|0 + If set to 'on' or '1', the eCAP service is treated as optional. + If the service cannot be reached or malfunctions, Squid will try + to ignore any errors and process the message as if the service was not enabled. No all eCAP errors can be bypassed. - If set to 0, the eCAP service is treated as essential and all - eCAP errors will result in an error page returned to the + If set to 'off' or '0', the eCAP service is treated as essential + and all eCAP errors will result in an error page returned to the HTTP client. - service_url = ecap://vendor/service_name?custom&cgi=style¶meters=optional + + Bypass is off by default: services are treated as essential. + + routing=on|off|1|0 + If set to 'on' or '1', the eCAP service is allowed to + dynamically change the current message adaptation plan by + returning a chain of services to be used next. + + Dynamic adaptation plan may cross or cover multiple supported + vectoring points in their natural processing order. + + Routing is not allowed by default. + + Older ecap_service format without optional named parameters is + deprecated but supported for backward compatibility. + Example: -ecap_service service_1 reqmod_precache 0 ecap://filters-R-us/leakDetector?on_error=block -ecap_service service_2 respmod_precache 1 icap://filters-R-us/virusFilter?config=/etc/vf.cfg +ecap_service s1 reqmod_precache ecap://filters.R.us/leakDetector?on_error=block bypass=off +ecap_service s2 respmod_precache ecap://filters.R.us/virusFilter config=/etc/vf.cfg bypass=on DOC_END NAME: loadable_modules