Hi all,
This patch add the 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"
The url_rewrtite_extras it is similar to the "key_extras" authenticator
helpers options. Originally developed to allow notes exchange between
authenicator helpers and redirector helpers.
In this patch we add a new type for cf.data the TokenOrQuotedString to
allow new configurations use quoted strings for the new option without
explicitly turning configuration_includes_quoted_values on.
This is a Measurement Factory project.
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<time_t>(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 <SP>] URL <SP> client_ip "/" fqdn <SP> user <SP> method [<SP> kv-pairs]<NL>
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<ClientRequestContext *>(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<clientReplyContext *>(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;
}