Fix those and I think this is a good part-1 patch that can be applied to
trunk.
Amos
found missing declaration in the flags struct.
a fixed patch included.
=== modified file 'src/ClientRequestContext.h'
--- src/ClientRequestContext.h 2012-08-14 11:53:07 +0000
+++ src/ClientRequestContext.h 2012-09-09 12:52:34 +0000
@@ -33,6 +33,8 @@
void clientAccessCheckDone(const allow_t &answer);
void clientRedirectStart();
void clientRedirectDone(char *result);
+ void clientStoreurlStart();
+ void clientStoreurlDone(char *result);
void checkNoCache();
void checkNoCacheDone(const allow_t &answer);
#if USE_ADAPTATION
@@ -53,7 +55,9 @@
ClientHttpRequest *http;
ACLChecklist *acl_checklist; /* need ptr back so we can unreg if needed */
int redirect_state;
+ int storeurl_state;
+ bool storeurl_done;
bool host_header_verify_done;
bool http_access_done;
bool adapted_http_access_done;
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2012-09-06 13:12:26 +0000
+++ src/client_side.cc 2012-09-09 12:54:28 +0000
@@ -714,6 +714,7 @@
ClientHttpRequest::freeResources()
{
safe_free(uri);
+ safe_free(store_uri);
safe_free(log_uri);
safe_free(redirect.location);
range_iter.boundary.clean();
=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc 2012-08-28 19:12:13 +0000
+++ src/client_side_request.cc 2012-09-09 13:01:23 +0000
@@ -131,6 +131,7 @@
static int clientHierarchical(ClientHttpRequest * http);
static void clientInterpretRequestHeaders(ClientHttpRequest * http);
static RH clientRedirectDoneWrapper;
+static RH clientStoreurlDoneWrapper;
static void checkNoCacheDoneWrapper(allow_t, void *);
extern "C" CSR clientGetMoreData;
extern "C" CSS clientReplyStatus;
@@ -151,10 +152,11 @@
debugs(85,3, HERE << this << " ClientRequestContext destructed");
}
-ClientRequestContext::ClientRequestContext(ClientHttpRequest *anHttp) : http(cbdataReference(anHttp)), acl_checklist (NULL), redirect_state (REDIRECT_NONE), error(NULL), readNextRequest(false)
+ClientRequestContext::ClientRequestContext(ClientHttpRequest *anHttp) : http(cbdataReference(anHttp)), acl_checklist (NULL), redirect_state (REDIRECT_NONE), storeurl_state (REDIRECT_NONE), error(NULL), readNextRequest(false)
{
http_access_done = false;
redirect_done = false;
+ storeurl_done = false;
no_cache_done = false;
interpreted_req_hdrs = false;
#if USE_SSL
@@ -916,6 +918,31 @@
redirectStart(http, clientRedirectDoneWrapper, this);
}
+static void
+clientStoreurlAccessCheckDone(allow_t answer, void *data)
+{
+ ClientRequestContext *context = (ClientRequestContext *)data;
+ ClientHttpRequest *http = context->http;
+ context->acl_checklist = NULL;
+
+ if (answer == ACCESS_ALLOWED)
+ storeurlStart(http, clientStoreurlDoneWrapper, context);
+ else
+ context->clientStoreurlDone(NULL);
+}
+
+void
+ClientRequestContext::clientStoreurlStart()
+{
+ debugs(33, 5, HERE << "' ClientRequestContext::clientStoreurlStart " << http->uri << "'");
+
+ if (Config.accessList.storeurl) {
+ acl_checklist = clientAclChecklistCreate(Config.accessList.storeurl, http);
+ acl_checklist->nonBlockingCheck(clientStoreurlAccessCheckDone, this);
+ } else
+ clientStoreurlDone(NULL)
+}
+
static int
clientHierarchical(ClientHttpRequest * http)
{
@@ -1262,6 +1289,37 @@
http->doCallouts();
}
+void
+clientStoreurlDoneWrapper(void *data, char *result)
+{
+ ClientRequestContext *calloutContext = (ClientRequestContext *)data;
+
+ if (!calloutContext->httpStateIsValid())
+ return;
+
+ calloutContext->clientStoreurlDone(result);
+}
+
+void
+ClientRequestContext::clientStoreurlDone(char *result)
+{
+ debugs(85, 5, "clientStoreurlDone: '" << http->uri << "' result=" << (result ? result : "NULL"));
+ assert(storeurl_state == REDIRECT_PENDING);
+ storeurl_state = REDIRECT_DONE;
+
+ /*
+ * the next step is to implement here the actuall store_url_rewrite proccess of pushing
+ * the store_url into thr http request.
+ */
+ if (result) {
+ debugs(85, DBG_CRITICAL, "A result for storu_url accepted: " << result);
+ } else {
+ debugs(85, DBG_CRITICAL, "A result for storu_url was not accepted: " << result);
+ }
+
+ http->doCallouts();
+}
+
/** Test cache allow/deny configuration
* Sets flags.cachable=1 if caching is not denied.
*/
@@ -1689,6 +1747,18 @@
if (ih != NULL)
ih->logType = logType;
#endif
+
+ if (!calloutContext->storeurl_done) {
+ calloutContext->storeurl_done = true;
+ assert(calloutContext->storeurl_state == REDIRECT_NONE);
+
+ if (Config.Program.storeurl) {
+ debugs(83, 3, HERE << "Doing calloutContext->clientSotreurlStart()");
+ calloutContext->storeurl_state = REDIRECT_PENDING;
+ calloutContext->clientStoreurlStart();
+ return;
+ }
+ }
}
#if !_USE_INLINE_
=== modified file 'src/client_side_request.h'
--- src/client_side_request.h 2012-08-28 19:12:13 +0000
+++ src/client_side_request.h 2012-09-09 13:03:15 +0000
@@ -98,6 +98,7 @@
HttpRequest *request; /* Parsed URL ... */
char *uri;
char *log_uri;
+ char *store_uri;
struct {
int64_t offset;
@@ -209,6 +210,7 @@
/* ones that should be elsewhere */
extern void redirectStart(ClientHttpRequest *, RH *, void *);
extern void tunnelStart(ClientHttpRequest *, int64_t *, int *);
+extern void storeurlStart(ClientHttpRequest *, RH *, void *);
#if _USE_INLINE_
#include "Store.h"
=== modified file 'src/redirect.cc'
--- src/redirect.cc 2012-08-28 19:12:13 +0000
+++ src/redirect.cc 2012-09-09 13:04:48 +0000
@@ -71,8 +71,11 @@
static HLPCB redirectHandleReply;
static void redirectStateFree(redirectStateData * r);
static helper *redirectors = NULL;
+static helper *storeurl_rewriters = NULL;
static OBJH redirectStats;
+static OBJH storeurlStats;
static int n_bypassed = 0;
+static int n_storeurl_bypassed = 0;
CBDATA_TYPE(redirectStateData);
static void
@@ -81,7 +84,7 @@
redirectStateData *r = static_cast<redirectStateData *>(data);
char *t;
void *cbdata;
- debugs(61, 5, "redirectHandleRead: {" << (reply && *reply != '\0' ? reply : "<NULL>") << "}");
+ debugs(61, 5, HERE << (reply && *reply != '\0' ? reply : "<NULL>") << "}");
if (reply) {
if ((t = strchr(reply, ' ')))
@@ -119,6 +122,21 @@
"because all redirectors were busy: %d\n", n_bypassed);
}
+static void
+storeurlStats(StoreEntry * sentry)
+{
+ if (storeurl_rewriters == NULL) {
+ storeAppendPrintf(sentry, "No Store Url Rewritters defined\n");
+ return;
+ }
+
+ helperStats(sentry, storeurl_rewriters, "Store Url Rewriters Statistics");
+
+ if (Config.onoff.storeurl_bypass)
+ storeAppendPrintf(sentry, "\nNumber of requests bypassed "
+ "because all Store Url Rewriters were busy: %d\n", n_storeurl_bypassed);
+}
+
/**** PUBLIC FUNCTIONS ****/
void
@@ -237,46 +255,171 @@
redirectRegisterWithCacheManager(void)
{
Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1);
+ Mgr::RegisterAction("storeurl", "Store URL Rewritter Stats", storeurlStats, 0, 1);
}
void
redirectInit(void)
{
- static int init = 0;
-
redirectRegisterWithCacheManager();
-
- if (!Config.Program.redirect)
+ if (!Config.Program.redirect && !Config.Program.storeurl)
return;
- if (redirectors == NULL)
- redirectors = new helper("redirector");
-
- redirectors->cmdline = Config.Program.redirect;
-
- redirectors->childs.updateLimits(Config.redirectChildren);
-
- redirectors->ipc_type = IPC_STREAM;
-
- helperOpenServers(redirectors);
-
- if (!init) {
- init = 1;
- CBDATA_INIT_TYPE(redirectStateData);
- }
+ if (Config.Program.redirect){
+ if (redirectors == NULL)
+ redirectors = new helper("redirector");
+
+ redirectors->cmdline = Config.Program.redirect;
+ redirectors->childs.updateLimits(Config.redirectChildren);
+ redirectors->ipc_type = IPC_STREAM;
+ helperOpenServers(redirectors);
+ }
+
+ if (Config.Program.storeurl){
+ if (storeurl_rewriters == NULL)
+ storeurl_rewriters = new helper("storeurl");
+
+ storeurl_rewriters->cmdline = Config.Program.storeurl;
+ storeurl_rewriters->childs.updateLimits(Config.storeurlChildren);
+ storeurl_rewriters->ipc_type = IPC_STREAM;
+ helperOpenServers(storeurl_rewriters);
+ }
+ static bool init = false;
+ if (init) {
+ init = true;
+ CBDATA_INIT_TYPE(redirectStateData);
+ }
}
void
redirectShutdown(void)
{
- if (!redirectors)
+ if (!redirectors && !storeurl_rewriters)
return;
- helperShutdown(redirectors);
+ if (redirectors)
+ helperShutdown(redirectors);
+
+ if (storeurl_rewriters)
+ helperShutdown(storeurl_rewriters);
if (!shutting_down)
return;
delete redirectors;
redirectors = NULL;
+ delete storeurl_rewriters;
+ storeurl_rewriters = NULL;
+}
+
+void
+storeurlStart(ClientHttpRequest * http, RH * handler, void *data)
+{
+ ConnStateData * conn = http->getConn();
+ redirectStateData *r = NULL;
+ const char *fqdn;
+ char buf[MAX_REDIRECTOR_REQUEST_STRLEN];
+ int sz;
+ http_status status;
+ char claddr[MAX_IPSTRLEN];
+ char myaddr[MAX_IPSTRLEN];
+ assert(http);
+ assert(handler);
+ debugs(61, 5, "storeurlStart: '" << http->uri << "'");
+
+ if (Config.onoff.storeurl_bypass && storeurl_rewriters->stats.queue_size) {
+ /* Skip store_url_rewritter if there is one request queued */
+ ++n_storeurl_bypassed;
+ handler(data, NULL);
+ return;
+ }
+
+ r = cbdataAlloc(redirectStateData);
+ r->orig_url = xstrdup(http->uri);
+ if (conn != NULL)
+ r->client_addr = conn->log_addr;
+ else
+ r->client_addr.SetNoAddr();
+ r->client_ident = NULL;
+#if USE_AUTH
+ if (http->request->auth_user_request != NULL) {
+ r->client_ident = http->request->auth_user_request->username();
+ debugs(61, 5, HERE << "auth-user=" << (r->client_ident?r->client_ident:"NULL"));
+ }
+#endif
+
+ // HttpRequest initializes with null_string. So we must check both defined() and size()
+ if (!r->client_ident && http->request->extacl_user.defined() && http->request->extacl_user.size()) {
+ r->client_ident = http->request->extacl_user.termedBuf();
+ debugs(61, 5, HERE << "acl-user=" << (r->client_ident?r->client_ident:"NULL"));
+ }
+
+ if (!r->client_ident && conn != NULL && conn->clientConnection != NULL && conn->clientConnection->rfc931[0]) {
+ r->client_ident = conn->clientConnection->rfc931;
+ debugs(61, 5, HERE << "ident-user=" << (r->client_ident?r->client_ident:"NULL"));
+ }
+
+#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",
+ r->orig_url,
+ r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
+ fqdn,
+ r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
+ r->method_s,
+ http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
+ http->request->my_addr.GetPort());
+
+ if ((sz<=0) || (sz>=MAX_REDIRECTOR_REQUEST_STRLEN)) {
+ if (sz<=0) {
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Can not build request to be passed to storeurl rewriter. Request ABORTED.");
+ } else {
+ status = HTTP_REQUEST_URI_TOO_LARGE;
+ debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to storeurl rewriter 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,
+ NULL,
+#if USE_AUTH
+ http->getConn() != NULL && http->getConn()->auth_user_request != NULL ?
+ http->getConn()->auth_user_request : http->request->auth_user_request);
+#else
+ NULL);
+#endif
+
+ node = (clientStreamNode *)http->client_stream.tail->data;
+ clientStreamRead(node, http, node->readBuffer);
+ return;
+ }
+
+ debugs(61,6, HERE << "sending '" << buf << "' to the helper");
+ helperSubmit(storeurl_rewriters, buf, redirectHandleReply, r);
}
=== modified file 'src/structs.h'
--- src/structs.h 2012-08-28 13:00:30 +0000
+++ src/structs.h 2012-09-09 15:29:07 +0000
@@ -306,6 +306,8 @@
#endif
wordlist *redirect;
+ wordlist *storeurl;
+
#if USE_UNLINKD
char *unlinkd;
@@ -323,6 +325,8 @@
#endif
HelperChildConfig redirectChildren;
+ HelperChildConfig storeurlChildren;
+
time_t authenticateGCInterval;
time_t authenticateTTL;
time_t authenticateIpTTL;
@@ -421,6 +425,7 @@
int nonhierarchical_direct;
int strip_query_terms;
int redirector_bypass;
+ int storeurl_bypass;
int ignore_unknown_nameservers;
int client_pconns;
int server_pconns;
@@ -484,6 +489,7 @@
acl_access *brokenPosts;
#endif
acl_access *redirector;
+ acl_access *storeurl;
acl_access *reply;
acl_address *outgoing_address;
#if USE_HTCP
@@ -962,7 +968,7 @@
};
struct request_flags {
- request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),hostVerified(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),pinned(0),canRePin(0),chunked_reply(0),stream_error(0),sslPeek(0),sslBumped(0),destinationIPLookedUp_(0) {
+ request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),storeurl_rewritted(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),hostVerified(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),pinned(0),canRePin(0),chunked_reply(0),stream_error(0),sslPeek(0),sslBumped(0),destinationIPLookedUp_(0) {
#if USE_HTTP_VIOLATIONS
nocache_hack = 0;
#endif
@@ -983,6 +989,7 @@
1; /* this should be killed, also in httpstateflags */
unsigned int refresh:1;
unsigned int redirected:1;
+ unsigned int storeurl_rewritted:1;
unsigned int need_validation:1;
unsigned int fail_on_validation_err:1; ///< whether we should fail if validation fails
unsigned int stale_if_hit:1; ///< reply is stale if it is a hit