=== modified file 'src/ClientRequestContext.h' --- src/ClientRequestContext.h 2012-08-14 11:53:07 +0000 +++ src/ClientRequestContext.h 2012-09-09 18:05:00 +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/HttpRequest.cc' --- src/HttpRequest.cc 2012-09-25 15:36:18 +0000 +++ src/HttpRequest.cc 2012-10-16 09:43:34 +0000 @@ -82,6 +82,7 @@ method = aMethod; protocol = aProtocol; urlpath = aUrlpath; + store_url = NULL; } void @@ -149,6 +150,8 @@ urlpath.clean(); + safe_free(store_url); + header.clean(); if (cache_control) { === modified file 'src/HttpRequest.h' --- src/HttpRequest.h 2012-10-04 09:14:06 +0000 +++ src/HttpRequest.h 2012-10-16 09:43:34 +0000 @@ -160,6 +160,8 @@ String urlpath; + char *store_url; + char *canonical; RequestFlags flags; === modified file 'src/MemObject.cc' --- src/MemObject.cc 2012-09-04 09:10:20 +0000 +++ src/MemObject.cc 2012-10-16 09:43:34 +0000 @@ -77,11 +77,31 @@ void MemObject::resetUrls(char const *aUrl, char const *aLog_url) { - safe_free(url); + safe_free(original_url); safe_free(log_url); /* XXX account log_url */ log_url = xstrdup(aLog_url); - url = xstrdup(aUrl); -} + original_url = xstrdup(aUrl); +} +/* +void +MemObject::initStoreUrl() +{ + store_url = xstrdup(request->store_url); +}*/ + +char * +MemObject::getStoreUrl() +{ + return xstrdup(request->store_url); + +} + +char * +MemObject::getOriginalUrl() +{ + return original_url; +} + MemObject::MemObject(char const *aUrl, char const *aLog_url) { @@ -89,7 +109,7 @@ HttpReply *rep = new HttpReply; _reply = HTTPMSGLOCK(rep); - url = xstrdup(aUrl); + original_url = xstrdup(aUrl); #if URL_CHECKSUM_DEBUG @@ -109,10 +129,10 @@ MemObject::~MemObject() { debugs(20, 3, HERE << "del MemObject " << this); - const Ctx ctx = ctx_enter(url); + const Ctx ctx = ctx_enter(original_url); #if URL_CHECKSUM_DEBUG - assert(chksum == url_checksum(url)); + assert(chksum == url_checksum(original_url)); #endif if (!shutting_down) @@ -135,7 +155,7 @@ ctx_exit(ctx); /* must exit before we free mem->url */ - safe_free(url); + safe_free(original_url); safe_free(log_url); /* XXX account log_url */ === modified file 'src/MemObject.h' --- src/MemObject.h 2012-09-22 20:07:31 +0000 +++ src/MemObject.h 2012-10-16 09:43:34 +0000 @@ -62,10 +62,14 @@ /// replaces construction-time URLs with correct ones; see hidden_mem_obj void resetUrls(char const *aUrl, char const *aLog_url); + void initStoreUrl(); + char * getStoreUrl(); + char * getOriginalUrl(); void write(StoreIOBuffer, STMCB *, void *); void unlinkRequest(); HttpReply const *getReply() const; + void replaceHttpReply(HttpReply *newrep); void stat (MemBuf * mb) const; int64_t endOffset () const; @@ -99,7 +103,8 @@ #endif HttpRequestMethod method; - char *url; + char *original_url; + char *store_url; mem_hdr data_hdr; int64_t inmem_lo; dlink_list clients; === modified file 'src/RequestFlags.h' --- src/RequestFlags.h 2012-09-19 17:16:56 +0000 +++ src/RequestFlags.h 2012-10-23 12:41:09 +0000 @@ -65,6 +65,8 @@ bool refresh :1; /** request was redirected by redirectors */ bool redirected :1; + /** request was rewritten using store_url helper*/ + bool store_url_rewritted :1; /** the requested object needs to be validated. See client_side_reply.cc * for further information. */ === modified file 'src/SquidConfig.h' --- src/SquidConfig.h 2012-10-09 23:15:44 +0000 +++ src/SquidConfig.h 2012-10-23 12:35:20 +0000 @@ -202,6 +202,7 @@ #endif wordlist *redirect; + wordlist *storeurl; #if USE_UNLINKD char *unlinkd; @@ -219,6 +220,7 @@ #endif HelperChildConfig redirectChildren; + HelperChildConfig storeurlChildren; time_t authenticateGCInterval; time_t authenticateTTL; time_t authenticateIpTTL; @@ -317,6 +319,7 @@ int nonhierarchical_direct; int strip_query_terms; int redirector_bypass; + int storeurl_bypass; int ignore_unknown_nameservers; int client_pconns; int server_pconns; @@ -380,6 +383,7 @@ acl_access *brokenPosts; #endif acl_access *redirector; + acl_access *storeurl; acl_access *reply; AclAddress *outgoing_address; #if USE_HTCP === modified file 'src/Store.h' --- src/Store.h 2012-10-16 00:18:09 +0000 +++ src/Store.h 2012-10-16 09:43:34 +0000 @@ -113,7 +113,8 @@ /// whether we are in the process of writing this entry to disk bool swappingOut() const { return swap_status == SWAPOUT_WRITING; } void swapOutFileClose(int how); - const char *url() const; + const char *originalUrl() const; + const char *storeUrl() const; int checkCachable(); int checkNegativeHit() const; int locked() const; === modified file 'src/StoreMetaURL.cc' --- src/StoreMetaURL.cc 2012-09-01 14:38:36 +0000 +++ src/StoreMetaURL.cc 2012-10-16 09:43:34 +0000 @@ -41,12 +41,12 @@ { assert (getType() == STORE_META_URL); - if (!e->mem_obj->url) + if (!e->mem_obj->original_url) return true; - if (strcasecmp(e->mem_obj->url, (char *)value)) { + if (strcasecmp(e->mem_obj->original_url, (char *)value)) { debugs(20, DBG_IMPORTANT, "storeClientReadHeader: URL mismatch"); - debugs(20, DBG_IMPORTANT, "\t{" << (char *) value << "} != {" << e->mem_obj->url << "}"); + debugs(20, DBG_IMPORTANT, "\t{" << (char *) value << "} != {" << e->mem_obj->original_url << "}"); return false; } === modified file 'src/acl/Asn.cc' --- src/acl/Asn.cc 2012-09-19 17:16:56 +0000 +++ src/acl/Asn.cc 2012-10-16 09:43:34 +0000 @@ -290,7 +290,7 @@ } if (result.length == 0 && asState->dataRead) { - debugs(53, 3, "asHandleReply: Done: " << e->url() ); + debugs(53, 3, "asHandleReply: Done: " << e->originalUrl() ); asStateFree(asState); return; } else if (result.flags.error) { @@ -355,7 +355,7 @@ debugs(53, 3, "asState->offset = " << asState->offset); if (e->store_status == STORE_PENDING) { - debugs(53, 3, "asHandleReply: store_status == STORE_PENDING: " << e->url() ); + debugs(53, 3, "asHandleReply: store_status == STORE_PENDING: " << e->originalUrl() ); StoreIOBuffer tempBuffer (AS_REQBUF_SZ - asState->reqofs, asState->offset, asState->reqbuf + asState->reqofs); @@ -366,7 +366,7 @@ asState); } else { StoreIOBuffer tempBuffer; - debugs(53, 3, "asHandleReply: store complete, but data received " << e->url() ); + debugs(53, 3, "asHandleReply: store complete, but data received " << e->originalUrl() ); tempBuffer.offset = asState->offset; tempBuffer.length = AS_REQBUF_SZ - asState->reqofs; tempBuffer.data = asState->reqbuf + asState->reqofs; @@ -382,7 +382,7 @@ asStateFree(void *data) { ASState *asState = (ASState *)data; - debugs(53, 3, "asnStateFree: " << asState->entry->url() ); + debugs(53, 3, "asnStateFree: " << asState->entry->originalUrl() ); storeUnregister(asState->sc, asState->entry, asState); asState->entry->unlock(); HTTPMSGUNLOCK(asState->request); === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2012-10-20 08:01:32 +0000 +++ src/cache_cf.cc 2012-10-23 11:45:43 +0000 @@ -700,6 +700,13 @@ } } + if (Config.Program.storeurl) { + if (Config.storeurlChildren.n_max < 1) { + Config.storeurlChildren.n_max = 0; + wordlistDestroy(&Config.Program.storeurl); + } + } + if (Config.appendDomain) if (*Config.appendDomain != '.') fatal("append_domain must begin with a '.'"); === modified file 'src/cache_manager.cc' --- src/cache_manager.cc 2012-09-18 14:06:31 +0000 +++ src/cache_manager.cc 2012-10-16 09:43:34 +0000 @@ -326,12 +326,12 @@ void CacheManager::Start(const Comm::ConnectionPointer &client, HttpRequest * request, StoreEntry * entry) { - debugs(16, 3, "CacheManager::Start: '" << entry->url() << "'" ); + debugs(16, 3, "CacheManager::Start: '" << entry->originalUrl() << "'" ); - Mgr::Command::Pointer cmd = ParseUrl(entry->url()); + Mgr::Command::Pointer cmd = ParseUrl(entry->originalUrl()); if (!cmd) { ErrorState *err = new ErrorState(ERR_INVALID_URL, HTTP_NOT_FOUND, request); - err->url = xstrdup(entry->url()); + err->url = xstrdup(entry->originalUrl()); errorAppendEntry(entry, err); entry->expires = squid_curtime; return; @@ -408,7 +408,7 @@ // special case: /squid-internal-mgr/ index page if (!strcmp(cmd->profile->name, "index")) { ErrorState err(MGR_INDEX, HTTP_OK, request); - err.url = xstrdup(entry->url()); + err.url = xstrdup(entry->originalUrl()); HttpReply *rep = err.BuildHttpReply(); if (strncmp(rep->body.content(),"Internal Error:", 15) == 0) rep->sline.status = HTTP_NOT_FOUND; === modified file 'src/cf.data.pre' --- src/cf.data.pre 2012-10-20 08:01:32 +0000 +++ src/cf.data.pre 2012-10-23 11:45:43 +0000 @@ -4167,6 +4167,69 @@ be allowed to request. DOC_END + + +COMMENT_START + OPTIONS FOR URL REWRITING + ----------------------------------------------------------------------------- +COMMENT_END + +NAME: url_storeurl_program storeurl_program +TYPE: wordlist +LOC: Config.Program.storeurl +DEFAULT: none +DOC_START + Specify the location of the executable URL rewriter to use. + + By default, a URL rewriter is not used. +DOC_END + +NAME: url_storeurl_children storeurl_children +TYPE: HelperChildConfig +DEFAULT: 20 startup=0 idle=1 concurrency=0 +LOC: Config.storeurlChildren +DOC_START + The maximum number of storeurlor processes to spawn. If you limit + + + startup= + + Sets a minimum of how many processes are to be spawned when Squid + + + idle= + + Sets a minimum of how many processes Squid is to try and keep available + + + concurrency= + + The number of requests each storeurlor helper can handle in + parallel. Defaults to 0 which indicates the storeurlor + +DOC_END + +NAME: url_storeurl_access storeurl_access +TYPE: acl_access +DEFAULT: none +LOC: Config.accessList.storeurl +DOC_START + If defined, this access list specifies which requests are + +DOC_END + +NAME: url_storeurl_bypass storeurl_bypass +TYPE: onoff +LOC: Config.onoff.storeurl_bypass +DEFAULT: off +DOC_START + When this is 'on', a request will not go through the + +DOC_END + + + + COMMENT_START OPTIONS FOR TUNING THE CACHE ----------------------------------------------------------------------------- === modified file 'src/client_side.cc' --- src/client_side.cc 2012-10-05 07:26:35 +0000 +++ src/client_side.cc 2012-10-16 09:43:34 +0000 @@ -4178,7 +4178,7 @@ if (vary) { /* Oops... something odd is going on here.. */ debugs(33, DBG_IMPORTANT, "varyEvaluateMatch: Oops. Not a Vary object on second attempt, '" << - entry->mem_obj->url << "' '" << vary << "'"); + entry->mem_obj->original_url << "' '" << vary << "'"); safe_free(request->vary_headers); return VARY_CANCEL; } @@ -4220,7 +4220,7 @@ * found the requested variant. Bail out */ debugs(33, DBG_IMPORTANT, "varyEvaluateMatch: Oops. Not a Vary match on second attempt, '" << - entry->mem_obj->url << "' '" << vary << "'"); + entry->mem_obj->original_url << "' '" << vary << "'"); return VARY_CANCEL; } } === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2012-10-04 09:14:06 +0000 +++ src/client_side_reply.cc 2012-10-23 22:54:54 +0000 @@ -365,7 +365,7 @@ if (deleting) return; - debugs(88, 3, "handleIMSReply: " << http->storeEntry()->url() << ", " << (long unsigned) result.length << " bytes" ); + debugs(88, 3, "handleIMSReply: " << http->storeEntry()->originalUrl() << ", " << (long unsigned) result.length << " bytes" ); if (http->storeEntry() == NULL) return; @@ -380,7 +380,7 @@ // request to origin was aborted if (EBIT_TEST(http->storeEntry()->flags, ENTRY_ABORTED)) { - debugs(88, 3, "handleIMSReply: request to origin aborted '" << http->storeEntry()->url() << "', sending old entry to client" ); + debugs(88, 3, "handleIMSReply: request to origin aborted '" << http->storeEntry()->originalUrl() << "', sending old entry to client" ); http->logType = LOG_TCP_REFRESH_FAIL_OLD; sendClientOldEntry(); } @@ -496,12 +496,11 @@ * Got the headers, now grok them */ assert(http->logType == LOG_TCP_HIT); - - if (strcmp(e->mem_obj->url, urlCanonical(r)) != 0) { - debugs(33, DBG_IMPORTANT, "clientProcessHit: URL mismatch, '" << e->mem_obj->url << "' != '" << urlCanonical(r) << "'"); - processMiss(); - return; - } + if (!r->store_url && strcmp(e->mem_obj->original_url, urlCanonical(r)) != 0) { + debugs(33, DBG_IMPORTANT, "clientProcessHit: URL mismatch, '" << e->mem_obj->original_url << "' != '" << urlCanonical(r) << "'"); + processMiss(); + return; + } switch (varyEvaluateMatch(e, r)) { @@ -935,7 +934,7 @@ if (!newEntry->isNull()) { /* Release the cached URI */ - debugs(88, 4, "clientPurgeRequest: GET '" << newEntry->url() << "'" ); + debugs(88, 4, "clientPurgeRequest: GET '" << newEntry->originalUrl() << "'" ); #if USE_HTCP neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(METHOD_GET), HTCP_CLR_PURGE); #endif @@ -951,7 +950,7 @@ clientReplyContext::purgeDoPurgeHead(StoreEntry *newEntry) { if (newEntry && !newEntry->isNull()) { - debugs(88, 4, "clientPurgeRequest: HEAD '" << newEntry->url() << "'" ); + debugs(88, 4, "clientPurgeRequest: HEAD '" << newEntry->originalUrl() << "'" ); #if USE_HTCP neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(METHOD_HEAD), HTCP_CLR_PURGE); #endif @@ -966,7 +965,7 @@ StoreEntry *entry = storeGetPublic(urlCanonical(http->request), METHOD_GET); if (entry) { - debugs(88, 4, "clientPurgeRequest: Vary GET '" << entry->url() << "'" ); + debugs(88, 4, "clientPurgeRequest: Vary GET '" << entry->originalUrl() << "'" ); #if USE_HTCP neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(METHOD_GET), HTCP_CLR_PURGE); #endif @@ -977,7 +976,7 @@ entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD); if (entry) { - debugs(88, 4, "clientPurgeRequest: Vary HEAD '" << entry->url() << "'" ); + debugs(88, 4, "clientPurgeRequest: Vary HEAD '" << entry->originalUrl() << "'" ); #if USE_HTCP neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(METHOD_HEAD), HTCP_CLR_PURGE); #endif @@ -2111,7 +2110,7 @@ " new bytes)"); debugs(88, 5, "clientReplyContext::sendMoreData:" << conn->clientConnection << - " '" << entry->url() << "'" << + " '" << entry->originalUrl() << "'" << " out.offset=" << http->out.offset); /* update size of the request */ === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2012-10-17 00:14:09 +0000 +++ src/client_side_request.cc 2012-10-23 11:45:43 +0000 @@ -130,6 +130,7 @@ static int clientHierarchical(ClientHttpRequest * http); static void clientInterpretRequestHeaders(ClientHttpRequest * http); static RH clientRedirectDoneWrapper; +static RH clientStoreurlDoneWrapper; static void checkNoCacheDoneWrapper(allow_t, void *); SQUIDCEXTERN CSR clientGetMoreData; SQUIDCEXTERN CSS clientReplyStatus; @@ -150,10 +151,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 @@ -915,6 +917,33 @@ 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{ + //storeurlStart(http, clientStoreurlDoneWrapper, this); + this->clientStoreurlDone(NULL); + } +} + static int clientHierarchical(ClientHttpRequest * http) { @@ -1256,6 +1285,58 @@ 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; + + if (result) { + + + + + } + + /* FIXME PIPELINE: This is innacurate during pipelining */ + + //if (http->getConn() != NULL && Comm::IsConnOpen(http->getConn()->clientConnection)) + //fd_note(http->getConn()->clientConnection->fd, http->uri); + + assert(http->uri); + + + /* + * TODO: 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 candidate recived from Store URL rewriter accepted: " << result); + assert(result != NULL); + assert(http->request->store_url == NULL); + http->request->store_url = xstrdup(result); + + } else { + debugs(85, DBG_CRITICAL, "No candidate recived from Store URL rewriter" ); + } + + + http->doCallouts(); +} +//end add for storeurl + /** Test cache allow/deny configuration * Sets flags.cachable=1 if caching is not denied. */ @@ -1585,6 +1666,17 @@ return; } + 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 (!calloutContext->interpreted_req_hdrs) { debugs(83, 3, HERE << "Doing clientInterpretRequestHeaders()"); calloutContext->interpreted_req_hdrs = 1; === modified file 'src/client_side_request.h' --- src/client_side_request.h 2012-09-25 16:38:36 +0000 +++ src/client_side_request.h 2012-10-23 22:53:52 +0000 @@ -208,6 +208,7 @@ /* ones that should be elsewhere */ void redirectStart(ClientHttpRequest *, RH *, void *); void tunnelStart(ClientHttpRequest *, int64_t *, int *); +void storeurlStart(ClientHttpRequest *, RH *, void *); #if _USE_INLINE_ #include "Store.h" === modified file 'src/forward.cc' --- src/forward.cc 2012-10-03 07:34:10 +0000 +++ src/forward.cc 2012-10-16 09:43:34 +0000 @@ -118,7 +118,7 @@ FwdState::FwdState(const Comm::ConnectionPointer &client, StoreEntry * e, HttpRequest * r, const AccessLogEntryPointer &alp): al(alp) { - debugs(17, 2, HERE << "Forwarding client request " << client << ", url=" << e->url() ); + debugs(17, 2, HERE << "Forwarding client request " << client << ", url=" << e->originalUrl() ); entry = e; clientConn = client; request = HTTPMSGLOCK(r); @@ -305,7 +305,7 @@ } } - debugs(17, 3, HERE << "'" << entry->url() << "'"); + debugs(17, 3, HERE << "'" << entry->originalUrl() << "'"); /* * This seems like an odd place to bind mem_obj and request. * Might want to assert that request is NULL at this point @@ -356,7 +356,7 @@ void FwdState::startConnectionOrFail() { - debugs(17, 3, HERE << entry->url()); + debugs(17, 3, HERE << entry->originalUrl()); if (serverDestinations.size() > 0) { // Ditch error page if it was created before. @@ -373,7 +373,7 @@ connectStart(); } else { - debugs(17, 3, HERE << "Connection failed: " << entry->url()); + debugs(17, 3, HERE << "Connection failed: " << entry->originalUrl()); if (!err) { ErrorState *anErr = new ErrorState(ERR_CANNOT_FORWARD, HTTP_INTERNAL_SERVER_ERROR, request); fail(anErr); @@ -385,7 +385,7 @@ void FwdState::fail(ErrorState * errorState) { - debugs(17, 3, HERE << err_type_str[errorState->type] << " \"" << httpStatusString(errorState->httpStatus) << "\"\n\t" << entry->url() ); + debugs(17, 3, HERE << err_type_str[errorState->type] << " \"" << httpStatusString(errorState->httpStatus) << "\"\n\t" << entry->originalUrl() ); delete err; err = errorState; @@ -405,7 +405,7 @@ void FwdState::unregister(Comm::ConnectionPointer &conn) { - debugs(17, 3, HERE << entry->url() ); + debugs(17, 3, HERE << entry->originalUrl() ); assert(serverConnection() == conn); assert(Comm::IsConnOpen(conn)); comm_remove_close_handler(conn->fd, fwdServerClosedWrapper, this); @@ -416,7 +416,7 @@ void FwdState::unregister(int fd) { - debugs(17, 3, HERE << entry->url() ); + debugs(17, 3, HERE << entry->originalUrl() ); assert(fd == serverConnection()->fd); unregister(serverConn); } @@ -430,7 +430,7 @@ void FwdState::complete() { - debugs(17, 3, HERE << entry->url() << "\n\tstatus " << entry->getReply()->sline.status ); + debugs(17, 3, HERE << entry->originalUrl() << "\n\tstatus " << entry->getReply()->sline.status ); #if URL_CHECKSUM_DEBUG entry->mem_obj->checkUrlChecksum(); @@ -439,7 +439,7 @@ logReplyStatus(n_tries, entry->getReply()->sline.status); if (reforward()) { - debugs(17, 3, HERE << "re-forwarding " << entry->getReply()->sline.status << " " << entry->url()); + debugs(17, 3, HERE << "re-forwarding " << entry->getReply()->sline.status << " " << entry->originalUrl()); if (Comm::IsConnOpen(serverConn)) unregister(serverConn); @@ -591,7 +591,7 @@ void FwdState::serverClosed(int fd) { - debugs(17, 2, HERE << "FD " << fd << " " << entry->url()); + debugs(17, 2, HERE << "FD " << fd << " " << entry->originalUrl()); retryOrBail(); } @@ -634,7 +634,7 @@ void FwdState::handleUnregisteredServerEnd() { - debugs(17, 2, HERE << "self=" << self << " err=" << err << ' ' << entry->url()); + debugs(17, 2, HERE << "self=" << self << " err=" << err << ' ' << entry->originalUrl()); assert(!Comm::IsConnOpen(serverConn)); retryOrBail(); } @@ -865,7 +865,7 @@ serverConn = conn; flags.connected_okay = true; - debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" ); + debugs(17, 3, HERE << serverConnection() << ": '" << entry->originalUrl() << "'" ); comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this); @@ -899,7 +899,7 @@ void FwdState::connectTimeout(int fd) { - debugs(17, 2, "fwdConnectTimeout: FD " << fd << ": '" << entry->url() << "'" ); + debugs(17, 2, "fwdConnectTimeout: FD " << fd << ": '" << entry->originalUrl() << "'" ); assert(serverDestinations[0] != NULL); assert(fd == serverDestinations[0]->fd); @@ -928,7 +928,7 @@ { assert(serverDestinations.size() > 0); - debugs(17, 3, "fwdConnectStart: " << entry->url()); + debugs(17, 3, "fwdConnectStart: " << entry->originalUrl()); if (n_tries == 0) // first attempt request->hier.first_conn_start = current_time; @@ -1074,7 +1074,7 @@ void FwdState::dispatch() { - debugs(17, 3, HERE << clientConn << ": Fetching '" << RequestMethodStr(request->method) << " " << entry->url() << "'"); + debugs(17, 3, HERE << clientConn << ": Fetching '" << RequestMethodStr(request->method) << " " << entry->originalUrl() << "'"); /* * Assert that server_fd is set. This is to guarantee that fwdState * is attached to something and will be deallocated when server_fd @@ -1082,7 +1082,7 @@ */ assert(Comm::IsConnOpen(serverConn)); - fd_note(serverConnection()->fd, entry->url()); + fd_note(serverConnection()->fd, entry->originalUrl()); fd_table[serverConnection()->fd].noteUse(fwdPconnPool); @@ -1173,7 +1173,7 @@ case AnyP::PROTO_WAIS: /* Not implemented */ default: - debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->url() << "'."); + debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->originalUrl() << "'."); ErrorState *anErr = new ErrorState(ERR_UNSUP_REQ, HTTP_BAD_REQUEST, request); fail(anErr); // Set the dont_retry flag because this is not a transient (network) error. @@ -1212,7 +1212,7 @@ e->mem_obj->checkUrlChecksum(); #endif - debugs(17, 3, HERE << e->url() << "?" ); + debugs(17, 3, HERE << e->originalUrl() << "?" ); if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { debugs(17, 3, HERE << "No, ENTRY_FWD_HDR_WAIT isn't set"); === modified file 'src/ftp.cc' --- src/ftp.cc 2012-10-10 17:06:38 +0000 +++ src/ftp.cc 2012-10-16 09:43:34 +0000 @@ -491,7 +491,7 @@ FtpStateData::FtpStateData(FwdState *theFwdState, const Comm::ConnectionPointer &conn) : AsyncJob("FtpStateData"), ServerStateData(theFwdState) { - const char *url = entry->url(); + const char *url = entry->originalUrl(); debugs(9, 3, HERE << "'" << url << "'" ); ++ statCounter.server.all.requests; ++ statCounter.server.ftp.requests; @@ -513,7 +513,7 @@ FtpStateData::~FtpStateData() { - debugs(9, 3, HERE << entry->url() ); + debugs(9, 3, HERE << entry->originalUrl() ); if (reply_hdr) { memFree(reply_hdr, MEM_8K_BUF); @@ -676,7 +676,7 @@ void FtpStateData::ftpTimeout(const CommTimeoutCbParams &io) { - debugs(9, 4, HERE << io.conn << ": '" << entry->url() << "'" ); + debugs(9, 4, HERE << io.conn << ": '" << entry->originalUrl() << "'" ); if (abortOnBadEntry("entry went bad while waiting for a timeout")) return; @@ -1122,7 +1122,7 @@ size_t len = data.readBuf->contentSize(); if (!len) { - debugs(9, 3, HERE << "no content to parse for " << entry->url() ); + debugs(9, 3, HERE << "no content to parse for " << entry->originalUrl() ); return; } @@ -1142,10 +1142,10 @@ if (usable == 0) { if (buf[0] == '\0' && len == 1) { - debugs(9, 3, HERE << "NIL ends data from " << entry->url() << " transfer problem?"); + debugs(9, 3, HERE << "NIL ends data from " << entry->originalUrl() << " transfer problem?"); data.readBuf->consume(len); } else { - debugs(9, 3, HERE << "didn't find end for " << entry->url()); + debugs(9, 3, HERE << "didn't find end for " << entry->originalUrl()); debugs(9, 3, HERE << "buffer remains (" << len << " bytes) '" << rfc1738_do_escape(buf,0) << "'"); } xfree(sbuf); @@ -2815,7 +2815,7 @@ temp->local.SetPort(0); } - ftpState->listenForDataChannel(temp, ftpState->entry->url()); + ftpState->listenForDataChannel(temp, ftpState->entry->originalUrl()); } /// \ingroup ServerProtocolFTPInternal @@ -3580,7 +3580,7 @@ http_status http_code; err_type err_code = ERR_NONE; - debugs(9, 3, HERE << ftpState->entry->url() << ", code " << code); + debugs(9, 3, HERE << ftpState->entry->originalUrl() << ", code " << code); if (cbdataReferenceValid(ftpState)) debugs(9, 5, HERE << "ftpState (" << ftpState << ") is valid!"); === modified file 'src/gopher.cc' --- src/gopher.cc 2012-09-04 09:10:20 +0000 +++ src/gopher.cc 2012-10-16 09:43:34 +0000 @@ -402,7 +402,7 @@ entry = gopherState->entry; if (gopherState->conversion == gopher_ds::HTML_INDEX_PAGE) { - char *html_url = html_quote(entry->url()); + char *html_url = html_quote(entry->originalUrl()); gopherHTMLHeader(entry, "Gopher Index %s", html_url); storeAppendPrintf(entry, "

This is a searchable Gopher index. Use the search\n" @@ -417,7 +417,7 @@ } if (gopherState->conversion == gopher_ds::HTML_CSO_PAGE) { - char *html_url = html_quote(entry->url()); + char *html_url = html_quote(entry->originalUrl()); gopherHTMLHeader(entry, "CSO Search of %s", html_url); storeAppendPrintf(entry, "

A CSO database usually contains a phonebook or\n" @@ -457,7 +457,7 @@ llen = left; } if (gopherState->len + llen >= TEMP_BUF_SIZE) { - debugs(10, DBG_IMPORTANT, "GopherHTML: Buffer overflow. Lost some data on URL: " << entry->url() ); + debugs(10, DBG_IMPORTANT, "GopherHTML: Buffer overflow. Lost some data on URL: " << entry->originalUrl() ); llen = TEMP_BUF_SIZE - gopherState->len - 1; } if (!lpos) { @@ -724,7 +724,7 @@ gopherTimeout(const CommTimeoutCbParams &io) { GopherStateData *gopherState = static_cast(io.data); - debugs(10, 4, HERE << io.conn << ": '" << gopherState->entry->url() << "'" ); + debugs(10, 4, HERE << io.conn << ": '" << gopherState->entry->originalUrl() << "'" ); gopherState->fwd->fail(new ErrorState(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, gopherState->fwd->request)); @@ -857,7 +857,7 @@ err = new ErrorState(ERR_WRITE_ERROR, HTTP_SERVICE_UNAVAILABLE, gopherState->fwd->request); err->xerrno = xerrno; err->port = gopherState->fwd->request->port; - err->url = xstrdup(entry->url()); + err->url = xstrdup(entry->originalUrl()); gopherState->fwd->fail(err); gopherState->serverConn->close(); @@ -967,7 +967,7 @@ gopherState->fwd = fwd; - debugs(10, 3, "gopherStart: " << entry->url() ); + debugs(10, 3, "gopherStart: " << entry->originalUrl() ); ++ statCounter.server.all.requests; === modified file 'src/htcp.cc' --- src/htcp.cc 2012-09-22 14:21:59 +0000 +++ src/htcp.cc 2012-10-16 09:43:34 +0000 @@ -1034,7 +1034,7 @@ static void htcpClrStoreEntry(StoreEntry * e) { - debugs(31, 4, "htcpClrStoreEntry: Clearing store for entry: " << e->url() ); + debugs(31, 4, "htcpClrStoreEntry: Clearing store for entry: " << e->originalUrl() ); e->releaseRequest(); } @@ -1578,7 +1578,7 @@ stuff.response = 0; stuff.msg_id = ++msg_id_counter; stuff.S.method = (char *) RequestMethodStr(req->method); - stuff.S.uri = (char *) e->url(); + stuff.S.uri = (char *) e->originalUrl(); stuff.S.version = vbuf; HttpStateData::httpBuildRequestHeader(req, e, NULL, &hdr, flags); mb.init(); @@ -1647,7 +1647,7 @@ } stuff.S.uri = xstrdup(uri); } else { - stuff.S.uri = (char *) e->url(); + stuff.S.uri = (char *) e->originalUrl(); } stuff.S.version = vbuf; if (reason != HTCP_CLR_INVALIDATION) { === modified file 'src/http.cc' --- src/http.cc 2012-10-20 08:01:32 +0000 +++ src/http.cc 2012-10-23 22:56:54 +0000 @@ -192,7 +192,7 @@ void HttpStateData::httpTimeout(const CommTimeoutCbParams ¶ms) { - debugs(11, 4, HERE << serverConnection << ": '" << entry->url() << "'" ); + debugs(11, 4, HERE << serverConnection << ": '" << entry->originalUrl() << "'" ); if (entry->store_status == STORE_PENDING) { fwd->fail(new ErrorState(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, fwd->request)); @@ -268,7 +268,7 @@ if (e->mem_obj->request) pe = storeGetPublicByRequest(e->mem_obj->request); else - pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method); + pe = storeGetPublic( e->mem_obj->original_url, e->mem_obj->method); if (pe != NULL) { assert(e != pe); @@ -285,7 +285,7 @@ if (e->mem_obj->request) pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD); else - pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD); + pe = storeGetPublic(e->mem_obj->original_url, METHOD_HEAD); if (pe != NULL) { assert(e != pe); @@ -348,7 +348,7 @@ * condition */ #define REFRESH_OVERRIDE(flag) \ - ((R = (R ? R : refreshLimits(entry->mem_obj->url))) , \ + ((R = (R ? R : refreshLimits(entry->mem_obj->original_url))) , \ (R && R->flags.flag)) #else #define REFRESH_OVERRIDE(flag) 0 @@ -665,7 +665,7 @@ if (Config.onoff.detect_broken_server_pconns && reply->bodySize(request->method) == -1 && !flags.chunked) { - debugs(11, DBG_IMPORTANT, "keepaliveAccounting: Impossible keep-alive header from '" << entry->url() << "'" ); + debugs(11, DBG_IMPORTANT, "keepaliveAccounting: Impossible keep-alive header from '" << entry->originalUrl() << "'" ); // debugs(11, 2, "GOT HTTP REPLY HDR:\n---------\n" << readBuf->content() << "\n----------" ); flags.keepalive_broken = true; } @@ -695,7 +695,7 @@ /** Creates a blank header. If this routine is made incremental, this will not do */ /* NP: all exit points to this function MUST call ctx_exit(ctx) */ - Ctx ctx = ctx_enter(entry->mem_obj->url); + Ctx ctx = ctx_enter(entry->mem_obj->original_url); debugs(11, 3, "processReplyHeader: key '" << entry->getMD5Text() << "'"); @@ -903,7 +903,7 @@ { ServerStateData::haveParsedReplyHeaders(); - Ctx ctx = ctx_enter(entry->mem_obj->url); + Ctx ctx = ctx_enter(entry->mem_obj->original_url); HttpReply *rep = finalReply(); if (rep->sline.status == HTTP_PARTIAL_CONTENT && @@ -1022,7 +1022,7 @@ * connection. */ if (!flags.request_sent) { - debugs(11, 2, "statusIfComplete: Request not yet fully sent \"" << RequestMethodStr(request->method) << " " << entry->url() << "\"" ); + debugs(11, 2, "statusIfComplete: Request not yet fully sent \"" << RequestMethodStr(request->method) << " " << entry->originalUrl() << "\"" ); return COMPLETE_NONPERSISTENT_MSG; } @@ -1272,7 +1272,7 @@ const http_status s = vrep->sline.status; const HttpVersion &v = vrep->sline.version; if (s == HTTP_INVALID_HEADER && v != HttpVersion(0,9)) { - debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Bad header encountered from " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); + debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Bad header encountered from " << entry->originalUrl() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); error = ERR_INVALID_RESP; } else if (s == HTTP_HEADER_TOO_LARGE) { fwd->dontRetry(true); @@ -1282,18 +1282,18 @@ } } else { // parsed headers but got no reply - debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: No reply at all for " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); + debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: No reply at all for " << entry->originalUrl() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); error = ERR_INVALID_RESP; } } else { assert(eof); if (readBuf->hasContent()) { error = ERR_INVALID_RESP; - debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Headers did not parse at all for " << entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); + debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Headers did not parse at all for " << entry->originalUrl() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); } else { error = ERR_ZERO_SIZE_OBJECT; debugs(11, (request->flags.accelerated?DBG_IMPORTANT:2), "WARNING: HTTP: Invalid Response: No object data received for " << - entry->url() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); + entry->originalUrl() << " AKA " << request->GetHost() << request->urlpath.termedBuf() ); } } @@ -1745,7 +1745,7 @@ static int warnedCount = 0; if (warnedCount++ < 100) { - const char *url = entry ? entry->url() : urlCanonical(request); + const char *url = entry ? entry->originalUrl() : urlCanonical(request); debugs(11, DBG_IMPORTANT, "Warning: likely forwarding loop with " << url); } } @@ -1814,7 +1814,7 @@ /* Add max-age only without no-cache */ if (!cc->hasMaxAge() && !cc->noCache()) { const char *url = - entry ? entry->url() : urlCanonical(request); + entry ? entry->originalUrl() : urlCanonical(request); cc->maxAge(getMaxAge(url)); } @@ -2060,7 +2060,7 @@ HttpVersion httpver(1,1); const char * url; if (_peer && !_peer->options.originserver) - url = entry->url(); + url = entry->originalUrl(); else url = request->urlpath.termedBuf(); mb->Printf("%s %s %s/%d.%d\r\n", @@ -2223,7 +2223,7 @@ void httpStart(FwdState *fwd) { - debugs(11, 3, "httpStart: \"" << RequestMethodStr(fwd->request->method) << " " << fwd->entry->url() << "\"" ); + debugs(11, 3, "httpStart: \"" << RequestMethodStr(fwd->request->method) << " " << fwd->entry->originalUrl() << "\"" ); AsyncJob::Start(new HttpStateData(fwd)); } @@ -2330,8 +2330,8 @@ // XXX: why does not this trigger a debug message on every request? if (flags.headers_parsed && !flags.abuse_detected) { - flags.abuse_detected = true; - debugs(11, DBG_IMPORTANT, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << request->client_addr << "' -> '" << entry->url() << "'" ); + flags.abuse_detected = true; + debugs(11, DBG_IMPORTANT, "http handleMoreRequestBodyAvailable: Likely proxy abuse detected '" << request->client_addr << "' -> '" << entry->originalUrl() << "'" ); if (virginReply()->sline.status == HTTP_INVALID_HEADER) { serverConnection->close(); === modified file 'src/mgr/Forwarder.cc' --- src/mgr/Forwarder.cc 2012-09-01 14:38:36 +0000 +++ src/mgr/Forwarder.cc 2012-10-16 09:43:34 +0000 @@ -68,7 +68,7 @@ void Mgr::Forwarder::handleError() { - debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->url() << " exceeds buffer size"); + debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->originalUrl() << " exceeds buffer size"); sendError(new ErrorState(ERR_INVALID_URL, HTTP_REQUEST_URI_TOO_LARGE, httpRequest)); mustStop("long URI"); } === modified file 'src/neighbors.cc' --- src/neighbors.cc 2012-09-22 13:26:23 +0000 +++ src/neighbors.cc 2012-10-16 09:43:34 +0000 @@ -580,7 +580,7 @@ int *exprep, int *timeout) { - const char *url = entry->url(); + const char *url = entry->originalUrl(); MemObject *mem = entry->mem_obj; CachePeer *p = NULL; int i; === modified file 'src/peer_select.cc' --- src/peer_select.cc 2012-09-19 17:16:56 +0000 +++ src/peer_select.cc 2012-10-16 09:43:34 +0000 @@ -91,7 +91,7 @@ peerSelectStateFree(ps_state * psstate) { if (psstate->entry) { - debugs(44, 3, HERE << psstate->entry->url()); + debugs(44, 3, HERE << psstate->entry->originalUrl()); if (psstate->entry->ping_status == PING_WAITING) eventDelete(peerPingTimeout, psstate); @@ -124,7 +124,7 @@ assert(entry); assert(entry->ping_status == PING_NONE); assert(direct != DIRECT_YES); - debugs(44, 3, "peerSelectIcpPing: " << entry->url() ); + debugs(44, 3, "peerSelectIcpPing: " << entry->originalUrl() ); if (!request->flags.hierarchical && direct != DIRECT_NO) return 0; @@ -150,7 +150,7 @@ ps_state *psstate; if (entry) - debugs(44, 3, "peerSelect: " << entry->url() ); + debugs(44, 3, "peerSelect: " << entry->originalUrl() ); else debugs(44, 3, "peerSelect: " << RequestMethodStr(request->method)); @@ -260,7 +260,7 @@ if (fs && psstate->paths->size() < (unsigned int)Config.forward_max_tries) { // send the next one off for DNS lookup. const char *host = fs->_peer ? fs->_peer->host : psstate->request->GetHost(); - debugs(44, 2, "Find IP destination for: " << psstate->entry->url() << "' via " << host); + debugs(44, 2, "Find IP destination for: " << psstate->entry->originalUrl() << "' via " << host); ipcache_nbgethostbyname(host, peerSelectDnsResults, psstate); return; } @@ -282,12 +282,12 @@ psstate->callback = NULL; if (psstate->paths->size() < 1) { - debugs(44, DBG_IMPORTANT, "Failed to select source for '" << psstate->entry->url() << "'"); + debugs(44, DBG_IMPORTANT, "Failed to select source for '" << psstate->entry->originalUrl() << "'"); debugs(44, DBG_IMPORTANT, " always_direct = " << psstate->always_direct); debugs(44, DBG_IMPORTANT, " never_direct = " << psstate->never_direct); debugs(44, DBG_IMPORTANT, " timedout = " << psstate->ping.timedout); } else { - debugs(44, 2, "Found sources for '" << psstate->entry->url() << "'"); + debugs(44, 2, "Found sources for '" << psstate->entry->originalUrl() << "'"); debugs(44, 2, " always_direct = " << psstate->always_direct); debugs(44, 2, " never_direct = " << psstate->never_direct); for (size_t i = 0; i < psstate->paths->size(); ++i) { @@ -738,7 +738,7 @@ StoreEntry *entry = psstate->entry; if (entry) - debugs(44, 3, "peerPingTimeout: '" << entry->url() << "'" ); + debugs(44, 3, "peerPingTimeout: '" << entry->originalUrl() << "'" ); if (!cbdataReferenceValid(psstate->callback_data)) { /* request aborted */ @@ -806,7 +806,7 @@ { ps_state *psstate = (ps_state *)data; icp_opcode op = header->getOpCode(); - debugs(44, 3, "peerHandleIcpReply: " << icp_opcode_str[op] << " " << psstate->entry->url() ); + debugs(44, 3, "peerHandleIcpReply: " << icp_opcode_str[op] << " " << psstate->entry->originalUrl() ); #if USE_CACHE_DIGESTS && 0 /* do cd lookup to count false misses */ @@ -841,7 +841,7 @@ ps_state *psstate = (ps_state *)data; debugs(44, 3, "peerHandleHtcpReply: " << (htcp->hit ? "HIT" : "MISS") << " " << - psstate->entry->url() ); + psstate->entry->originalUrl() ); ++ psstate->ping.n_recv; if (htcp->hit) { === modified file 'src/redirect.cc' --- src/redirect.cc 2012-09-04 09:10:20 +0000 +++ src/redirect.cc 2012-10-16 09:43:34 +0000 @@ -69,8 +69,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 @@ -79,7 +82,7 @@ redirectStateData *r = static_cast(data); char *t; void *cbdata; - debugs(61, 5, "redirectHandleRead: {" << (reply && *reply != '\0' ? reply : "") << "}"); + debugs(61, 5, HERE << (reply && *reply != '\0' ? reply : "") << "}"); if (reply) { if ((t = strchr(reply, ' '))) @@ -117,6 +120,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 @@ -235,6 +253,7 @@ redirectRegisterWithCacheManager(void) { Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1); + Mgr::RegisterAction("storeurl", "Store URL Rewritter Stats", storeurlStats, 0, 1); } void @@ -244,37 +263,164 @@ 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 (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); + } if (!init) { - init = 1; - CBDATA_INIT_TYPE(redirectStateData); - } + init = 1; + 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 rewriter 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 redirector. Request ABORTED."); + } else { + status = HTTP_REQUEST_URI_TOO_LARGE; + debugs(61, DBG_CRITICAL, "ERROR: Gateway Failure. Request passed to storeurl rewritter 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, + 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/refresh.cc' --- src/refresh.cc 2012-09-19 17:16:56 +0000 +++ src/refresh.cc 2012-10-16 09:43:34 +0000 @@ -240,7 +240,7 @@ stale_flags sf; if (entry->mem_obj) - uri = entry->mem_obj->url; + uri = entry->mem_obj->original_url; else if (request) uri = urlCanonical(request); === modified file 'src/repl/heap/store_heap_replacement.cc' --- src/repl/heap/store_heap_replacement.cc 2012-09-01 14:38:36 +0000 +++ src/repl/heap/store_heap_replacement.cc 2012-10-16 09:43:34 +0000 @@ -90,8 +90,8 @@ " refcnt=" << e->refcount << " lastref=" << e->lastref << " heap_age=" << heap_age << " tie=" << tie << " -> " << key); - if (e->mem_obj && e->mem_obj->url) - debugs(81, 3, "HeapKeyGen_StoreEntry_LFUDA: url=" << e->mem_obj->url); + if (e->mem_obj && e->mem_obj->original_url) + debugs(81, 3, "HeapKeyGen_StoreEntry_LFUDA: url=" << e->mem_obj->original_url); return (double) key; } @@ -128,8 +128,8 @@ e->lastref << " heap_age=" << heap_age << " tie=" << tie << " -> " << key); - if (e->mem_obj && e->mem_obj->url) - debugs(81, 3, "HeapKeyGen_StoreEntry_GDSF: url=" << e->mem_obj->url); + if (e->mem_obj && e->mem_obj->original_url) + debugs(81, 3, "HeapKeyGen_StoreEntry_GDSF: url=" << e->mem_obj->original_url); return key; } @@ -149,8 +149,8 @@ e->getMD5Text() << " heap_age=" << heap_age << " lastref=" << (double) e->lastref ); - if (e->mem_obj && e->mem_obj->url) - debugs(81, 3, "HeapKeyGen_StoreEntry_LRU: url=" << e->mem_obj->url); + if (e->mem_obj && e->mem_obj->original_url) + debugs(81, 3, "HeapKeyGen_StoreEntry_LRU: url=" << e->mem_obj->original_url); return (heap_key) e->lastref; } === modified file 'src/store.cc' --- src/store.cc 2012-10-05 23:36:22 +0000 +++ src/store.cc 2012-10-16 09:43:34 +0000 @@ -686,7 +686,7 @@ if (mem_obj != NULL) { mem_obj->id = getKeyCounter(); - newkey = storeKeyPrivate(mem_obj->url, mem_obj->method, mem_obj->id); + newkey = storeKeyPrivate(mem_obj->original_url, mem_obj->method, mem_obj->id); } else { newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter()); } @@ -738,7 +738,7 @@ * to record the new variance key */ safe_free(request->vary_headers); /* free old "bad" variance key */ - StoreEntry *pe = storeGetPublic(mem_obj->url, mem_obj->method); + StoreEntry *pe = storeGetPublic(mem_obj->original_url, mem_obj->method); if (pe) pe->release(); @@ -755,10 +755,11 @@ // TODO: storeGetPublic() calls below may create unlocked entries. // We should add/use storeHas() API or lock/unlock those entries. - if (mem_obj->vary_headers && !storeGetPublic(mem_obj->url, mem_obj->method)) { + if (mem_obj->vary_headers && !storeGetPublic(mem_obj->original_url, mem_obj->method)) { /* Create "vary" base object */ String vary; - StoreEntry *pe = storeCreateEntry(mem_obj->url, mem_obj->log_url, request->flags, request->method); + StoreEntry *pe = storeCreateEntry(mem_obj->original_url , mem_obj->log_url, request->flags, request->method); + /* We are allowed to do this typecast */ HttpReply *rep = new HttpReply; rep->setHeaders(HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000); @@ -793,17 +794,18 @@ newkey = storeKeyPublicByRequest(mem_obj->request); } else - newkey = storeKeyPublic(mem_obj->url, mem_obj->method); + newkey = storeKeyPublic(mem_obj->original_url, mem_obj->method); if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) { - debugs(20, 3, "StoreEntry::setPublicKey: Making old '" << mem_obj->url << "' private."); + debugs(20, 3, "StoreEntry::setPublicKey: Making old '" << mem_obj->original_url << "' private."); e2->setPrivateKey(); e2->release(); if (mem_obj->request) newkey = storeKeyPublicByRequest(mem_obj->request); else - newkey = storeKeyPublic(mem_obj->url, mem_obj->method); + newkey = storeKeyPublic(mem_obj->original_url, mem_obj->method); + } if (key) @@ -1644,19 +1646,19 @@ assert(mem_obj->inmem_lo == 0); if (EBIT_TEST(flags, ENTRY_SPECIAL)) { - debugs(20, 4, "StoreEntry::setMemStatus: not inserting special " << mem_obj->url << " into policy"); + debugs(20, 4, "StoreEntry::setMemStatus: not inserting special " << mem_obj->original_url << " into policy"); } else { mem_policy->Add(mem_policy, this, &mem_obj->repl); - debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url << " key: " << getMD5Text()); + debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->original_url << " key: " << getMD5Text()); } ++hot_obj_count; // TODO: maintain for the shared hot cache as well } else { if (EBIT_TEST(flags, ENTRY_SPECIAL)) { - debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->url); + debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->original_url); } else { mem_policy->Remove(mem_policy, this, &mem_obj->repl); - debugs(20, 4, "StoreEntry::setMemStatus: removed mem node " << mem_obj->url); + debugs(20, 4, "StoreEntry::setMemStatus: removed mem node " << mem_obj->original_url); } --hot_obj_count; @@ -1666,14 +1668,33 @@ } const char * -StoreEntry::url() const -{ - if (this == NULL) - return "[null_entry]"; - else if (mem_obj == NULL) - return "[null_mem_obj]"; - else - return mem_obj->url; +StoreEntry::originalUrl() const +{ + + + if (this == NULL) + return "[null_entry]"; + else if (mem_obj == NULL) + return "[null_mem_obj]"; + else{ + debugs(20, 3, HERE << "A storeEntry::origianlUrl being used here using URL:" << mem_obj->original_url); + debugs(20, 3, HERE << "A storeEntry::origianlUrl Could be used with URL:" << mem_obj->request->store_url); + + return mem_obj->original_url; + } +} + +const char * +StoreEntry::storeUrl() const +{ + if (this == NULL) + return "[null_entry]"; + else if (mem_obj == NULL) + return "[null_mem_obj]"; + else{ + debugs(20, 3, HERE << "A storeEntry::storeUrl used with URL:" << mem_obj->request->store_url); + return (const char *)mem_obj->request->store_url; + } } void @@ -1738,7 +1759,7 @@ StoreEntry::reset() { assert (mem_obj); - debugs(20, 3, "StoreEntry::reset: " << url()); + debugs(20, 3, "StoreEntry::reset: " << originalUrl()); mem_obj->reset(); HttpReply *rep = (HttpReply *) getReply(); // bypass const rep->reset(); @@ -1832,7 +1853,7 @@ void StoreEntry::replaceHttpReply(HttpReply *rep, bool andStartWriting) { - debugs(20, 3, "StoreEntry::replaceHttpReply: " << url()); + debugs(20, 3, "StoreEntry::replaceHttpReply: " << originalUrl()); if (!mem_obj) { debugs(20, DBG_CRITICAL, "Attempt to replace object with no in-memory representation"); @@ -1921,7 +1942,7 @@ if (mod_time < 0) mod_time = timestamp; - debugs(88, 3, "modifiedSince: '" << url() << "'"); + debugs(88, 3, "modifiedSince: '" << originalUrl() << "'"); debugs(88, 3, "modifiedSince: mod_time = " << mod_time); === modified file 'src/store_client.cc' --- src/store_client.cc 2012-09-18 21:05:32 +0000 +++ src/store_client.cc 2012-10-16 09:43:34 +0000 @@ -716,7 +716,7 @@ if (sc->_callback.pending()) { /* callback with ssize = -1 to indicate unexpected termination */ - debugs(90, 3, "storeUnregister: store_client for " << mem->url << " has a callback"); + debugs(90, 3, "storeUnregister: store_client for " << mem->original_url << " has a callback"); sc->fail(); } === modified file 'src/store_key_md5.cc' --- src/store_key_md5.cc 2012-09-01 14:38:36 +0000 +++ src/store_key_md5.cc 2012-10-16 09:43:34 +0000 @@ -112,12 +112,14 @@ SquidMD5Update(&M, (unsigned char *) &method, sizeof(method)); SquidMD5Update(&M, (unsigned char *) url, strlen(url)); SquidMD5Final(digest, &M); + debugs(20, 3, "storeKeyPrivate was created using method and url is: " ); return digest; } const cache_key * storeKeyPublic(const char *url, const HttpRequestMethod& method) { + debugs(20, 2, "storeKeypublicwith URL and method: " << RequestMethodStr(method) << " " << url); static cache_key digest[SQUID_MD5_DIGEST_LENGTH]; unsigned char m = (unsigned char) method.id(); SquidMD5_CTX M; @@ -125,6 +127,7 @@ SquidMD5Update(&M, &m, sizeof(m)); SquidMD5Update(&M, (unsigned char *) url, strlen(url)); SquidMD5Final(digest, &M); + debugs(20, 3, "storeKeypublicreuest was created using method and url is: " ); return digest; } @@ -140,16 +143,21 @@ static cache_key digest[SQUID_MD5_DIGEST_LENGTH]; unsigned char m = (unsigned char) method.id(); const char *url = urlCanonical(request); + if (request->store_url!= NULL) + url = request->store_url; + debugs(20, 3, "storeKeypublicreuest could be with URL and method: " << RequestMethodStr(method) << " " << url); + SquidMD5_CTX M; SquidMD5Init(&M); SquidMD5Update(&M, &m, sizeof(m)); SquidMD5Update(&M, (unsigned char *) url, strlen(url)); + debugs(20, 3, "storeKeypublicreuest with URL and method: " << RequestMethodStr(method) << " " << url); if (request->vary_headers) SquidMD5Update(&M, (unsigned char *) request->vary_headers, strlen(request->vary_headers)); SquidMD5Final(digest, &M); - + debugs(20, 3, "storeKeypublicreuest was created using method and url from request" ); return digest; } === modified file 'src/store_log.cc' --- src/store_log.cc 2012-09-04 09:10:20 +0000 +++ src/store_log.cc 2012-10-16 09:43:34 +0000 @@ -71,9 +71,9 @@ ++storeLogTagsCounts[tag]; if (mem != NULL) { if (mem->log_url == NULL) { - debugs(20, DBG_IMPORTANT, "storeLog: NULL log_url for " << mem->url); + debugs(20, DBG_IMPORTANT, "storeLog: NULL log_url for " << mem->original_url); mem->dump(); - mem->log_url = xstrdup(mem->url); + mem->log_url = xstrdup(mem->original_url); } reply = e->getReply(); === modified file 'src/store_swapmeta.cc' --- src/store_swapmeta.cc 2012-09-01 14:38:36 +0000 +++ src/store_swapmeta.cc 2012-10-16 09:43:34 +0000 @@ -63,12 +63,16 @@ tlv *TLV = NULL; /* we'll return this */ tlv **T = &TLV; const char *url; + const char *storeUrl; const char *vary; assert(e->mem_obj != NULL); const int64_t objsize = e->mem_obj->expectedReplySize(); assert(e->swap_status == SWAPOUT_WRITING); - url = e->url(); + url = e->originalUrl(); + storeUrl = e->storeUrl(); debugs(20, 3, "storeSwapMetaBuild: " << url ); + debugs(20, 3, "storeSwapMetaBuild: mem object store_url is:" << e->storeUrl()); + debugs(20, 3, "storeurl meta can be used with:" << storeUrl ); tlv *t = StoreMeta::Factory (STORE_META_KEY,SQUID_MD5_DIGEST_LENGTH, e->key); if (!t) { @@ -92,6 +96,12 @@ return NULL; } + if(storeUrl) { + debugs(20, 3, "storeSwapMetaBuild: building storeurl meta " << storeUrl ); + //t = StoreMeta::Factory(STORE_META_STOREURL, strlen(storeUrl) + 1, storeUrl); + //T = StoreMeta::Add(T, t); + } + if (objsize >= 0) { T = StoreMeta::Add(T, t); t = StoreMeta::Factory(STORE_META_OBJSIZE, sizeof(objsize), &objsize); @@ -115,7 +125,6 @@ StoreMeta::Add (T, t); } - return TLV; } === modified file 'src/store_swapout.cc' --- src/store_swapout.cc 2012-09-04 09:10:20 +0000 +++ src/store_swapout.cc 2012-10-16 09:43:34 +0000 @@ -65,7 +65,7 @@ /* Build the swap metadata, so the filesystem will know how much * metadata there is to store */ - debugs(20, 5, "storeSwapOutStart: Begin SwapOut '" << e->url() << "' to dirno " <<