On 10/06/2011 12:51 AM, Amos Jeffries wrote:
On Wed, 05 Oct 2011 11:32:39 +0300, Tsantilas Christos wrote:
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.
Since you alter the way the 0/1 backward compatibility is parsed please
take the opportunity to add a debugs() "UPGRADE: " message at level
"(opt_parse_cfg_only?0:1)" to the cases. Stating that option format has
changed and what it should be upgraded to.
Done
In the duplicate warning message:
- s/Douplicate/Duplicate/
- s/ataptation/adaptation/
done
Amos
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-06 09:10:48 +0000
@@ -1,28 +1,29 @@
/*
* DEBUG: section 93 Adaptation
*/
#include "squid.h"
#include "ConfigParser.h"
#include "adaptation/ServiceConfig.h"
#include "ip/tools.h"
+#include <set>
Adaptation::ServiceConfig::ServiceConfig():
port(-1), method(methodNone), point(pointNone),
bypass(false), maxConn(-1), onOverload(srvWait),
routing(false), ipv6(false)
{}
const char *
Adaptation::ServiceConfig::methodStr() const
{
return Adaptation::methodStr(method);
}
const char *
Adaptation::ServiceConfig::vectPointStr() const
{
return Adaptation::vectPointStr(point);
}
Adaptation::Method
@@ -52,98 +53,106 @@
if (!strcasecmp(t, "postcache"))
return Adaptation::pointPostCache;
return Adaptation::pointNone;
}
bool
Adaptation::ServiceConfig::parse()
{
String method_point;
ConfigParser::ParseString(&key);
ConfigParser::ParseString(&method_point);
method = parseMethod(method_point.termedBuf());
point = parseVectPoint(method_point.termedBuf());
// reset optional parameters in case we are reconfiguring
bypass = routing = false;
// handle optional service name=value parameters
- const char *lastOption = NULL;
bool grokkedUri = false;
bool onOverloadSet = false;
+ std::set<std::string> 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;
+ name = "bypass";
+ value = "off";
+ debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=off' option to disable service bypass");
+ } else if (strcmp(option, "1") == 0) { // backward compatibility
+ name = "bypass";
+ value = "on";
+ debugs(3, opt_parse_cfg_only?0:1, "UPGRADE: Please use 'bypass=on' option to enable service bypass");
+ } 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 '='
+ }
}
- const char *name = option;
- char *value = strstr(option, "=");
- if (!value) {
- lastOption = option;
- break;
+ // Check if option is set twice
+ if (options.find(name) != options.end()) {
+ debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " <<
+ "Duplicate option \"" << name << "\" in adaptation service definition");
+ return false;
}
- *value = '\0'; // terminate option name
- ++value; // skip '='
+ options.insert(name);
- // TODO: warn if option is set twice?
bool grokked = false;
if (strcmp(name, "bypass") == 0) {
grokked = grokBool(bypass, name, value);
} else if (strcmp(name, "routing") == 0)
grokked = grokBool(routing, name, value);
else if (strcmp(name, "uri") == 0)
grokked = grokkedUri = grokUri(value);
else if (strcmp(name, "ipv6") == 0) {
grokked = grokBool(ipv6, name, value);
if (grokked && ipv6 && !Ip::EnableIpv6)
debugs(3, DBG_IMPORTANT, "WARNING: IPv6 is disabled. ICAP service option ignored.");
} else if (strcmp(name, "max-conn") == 0)
grokked = grokLong(maxConn, name, value);
else if (strcmp(name, "on-overload") == 0) {
grokked = grokOnOverload(onOverload, value);
onOverloadSet = true;
} else
grokked = grokExtension(name, value);
if (!grokked)
return false;
}
// set default on-overload value if needed
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;
}
debugs(3,5, cfg_filename << ':' << config_lineno << ": " <<
"adaptation_service " << key << ' ' <<
methodStr() << "_" << vectPointStr() << ' ' <<
bypass << routing << ' ' <<
uri);
return true;
}
bool
Adaptation::ServiceConfig::grokUri(const char *value)
{
// TODO: find core code that parses URLs and extracts various parts
// AYJ: most of this is duplicate of urlParse() in src/url.cc
if (!value || !*value) {
debugs(3, 0, HERE << cfg_filename << ':' << config_lineno << ": " <<
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2011-09-22 00:46:26 +0000
+++ src/cf.data.pre 2011-10-06 08:42:00 +0000
@@ -6579,51 +6579,53 @@
DOC_END
NAME: icap_client_username_encode
TYPE: onoff
IFDEF: ICAP_CLIENT
COMMENT: on|off
LOC: Adaptation::Icap::TheConfig.client_username_encode
DEFAULT: off
DOC_START
Whether to base64 encode the authenticated client username.
DOC_END
NAME: icap_service
TYPE: icap_service_type
IFDEF: ICAP_CLIENT
LOC: Adaptation::Icap::TheConfig
DEFAULT: none
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
transactions. Squid does not enforce that requirement. You can specify
services with the same service_url and different vectoring_points. You
can even specify multiple identical services as long as their
service_names differ.
Service options are separated by white space. ICAP services support
the following name=value options:
bypass=on|off|1|0
If set to 'on' or '1', the ICAP 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 ICAP errors can be
bypassed. If set to 0, the ICAP service is treated as
essential and all ICAP errors will result in an error page
returned to the HTTP client.
@@ -6658,42 +6660,42 @@
* bypass: ignore the "over-connected" ICAP service
* wait: wait (in a FIFO queue) for an ICAP connection slot
* force: proceed, ignoring the Max-Connections limit
In SMP mode with N workers, each worker assumes the service
connection limit is Max-Connections/N, even though not all
workers may use a given service.
The default value is "bypass" if service is bypassable,
otherwise it is set to "wait".
max-conn=number
Use the given number as the Max-Connections limit, regardless
of the Max-Connections value given by the service, if any.
Older icap_service format without optional named parameters is
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
TYPE: icap_class_type
IFDEF: ICAP_CLIENT
LOC: none
DEFAULT: none
DOC_START
This deprecated option was documented to define an ICAP service
chain, even though it actually defined a set of similar, redundant
services, and the chains were not supported.
To define a set of redundant services, please use the
adaptation_service_set directive. For service chains, use
adaptation_service_chain.
DOC_END
NAME: icap_access
TYPE: icap_access_type
IFDEF: ICAP_CLIENT
@@ -6711,59 +6713,90 @@
COMMENT_END
NAME: ecap_enable
TYPE: onoff
IFDEF: USE_ECAP
COMMENT: on|off
LOC: Adaptation::Ecap::TheConfig.onoff
DEFAULT: off
DOC_START
Controls whether eCAP support is enabled.
DOC_END
NAME: ecap_service
TYPE: ecap_service_type
IFDEF: USE_ECAP
LOC: Adaptation::Ecap::TheConfig
DEFAULT: none
DOC_START
Defines a single eCAP service
- ecap_service servicename vectoring_point bypass service_url
+ ecap_service id vectoring_point uri [option ...]
- vectoring_point = reqmod_precache|reqmod_postcache|respmod_precache|respmod_postcache
+ 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
TYPE: wordlist
IFDEF: USE_LOADABLE_MODULES
LOC: Config.loadable_module_names
DEFAULT: none
DOC_START
Instructs Squid to load the specified dynamic module(s) or activate
preloaded module(s).
Example:
loadable_modules @DEFAULT_PREFIX@/lib/MinimalAdapter.so
DOC_END
COMMENT_START
MESSAGE ADAPTATION OPTIONS
-----------------------------------------------------------------------------
COMMENT_END
NAME: adaptation_service_set