=== modified file 'src/FwdState.cc'
--- src/FwdState.cc	2014-04-25 13:38:22 +0000
+++ src/FwdState.cc	2014-04-26 05:20:29 +0000
@@ -304,87 +304,90 @@
     serverDestinations.clear();
 
     debugs(17, 3, HERE << "FwdState destructor done");
 }
 
 /**
  * This is the entry point for client-side to start forwarding
  * a transaction.  It is a static method that may or may not
  * allocate a FwdState.
  */
 void
 FwdState::Start(const Comm::ConnectionPointer &clientConn, StoreEntry *entry, HttpRequest *request, const AccessLogEntryPointer &al)
 {
     /** \note
      * client_addr == no_addr indicates this is an "internal" request
      * from peer_digest.c, asn.c, netdb.c, etc and should always
      * be allowed.  yuck, I know.
      */
 
     if ( Config.accessList.miss && !request->client_addr.isNoAddr() &&
-            request->protocol != AnyP::PROTO_INTERNAL && request->protocol != AnyP::PROTO_CACHE_OBJECT) {
+            !request->flags.internal && request->url.getScheme() != AnyP::PROTO_CACHE_OBJECT) {
         /**
          * Check if this host is allowed to fetch MISSES from us (miss_access).
          * Intentionally replace the src_addr automatically selected by the checklist code
          * we do NOT want the indirect client address to be tested here.
          */
         ACLFilledChecklist ch(Config.accessList.miss, request, NULL);
         ch.src_addr = request->client_addr;
         if (ch.fastCheck() == ACCESS_DENIED) {
             err_type page_id;
             page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName, 1);
 
             if (page_id == ERR_NONE)
                 page_id = ERR_FORWARDING_DENIED;
 
             ErrorState *anErr = new ErrorState(page_id, Http::scForbidden, request);
             errorAppendEntry(entry, anErr);	// frees anErr
             return;
         }
     }
 
     debugs(17, 3, HERE << "'" << entry->url() << "'");
     /*
      * This seems like an odd place to bind mem_obj and request.
      * Might want to assert that request is NULL at this point
      */
     entry->mem_obj->request = request;
     HTTPMSGLOCK(entry->mem_obj->request);
 #if URL_CHECKSUM_DEBUG
 
     entry->mem_obj->checkUrlChecksum();
 #endif
 
     if (shutting_down) {
         /* more yuck */
         ErrorState *anErr = new ErrorState(ERR_SHUTTING_DOWN, Http::scServiceUnavailable, request);
         errorAppendEntry(entry, anErr);	// frees anErr
         return;
     }
 
-    switch (request->protocol) {
-
-    case AnyP::PROTO_INTERNAL:
+    if (request->flags.internal) {
+        debugs(17, 2, "calling internalStart() due to request flag");
         internalStart(clientConn, request, entry);
         return;
+    }
+
+    switch (request->url.getScheme()) {
 
     case AnyP::PROTO_CACHE_OBJECT:
+        debugs(17, 2, "calling CacheManager due to request scheme " << request->url.getScheme());
         CacheManager::GetInstance()->Start(clientConn, request, entry);
         return;
 
     case AnyP::PROTO_URN:
         urnStart(request, entry);
         return;
 
     default:
         FwdState::Pointer fwd = new FwdState(clientConn, entry, request, al);
         fwd->start(fwd);
         return;
     }
 
     /* NOTREACHED */
 }
 
 void
 FwdState::fwdStart(const Comm::ConnectionPointer &clientConn, StoreEntry *entry, HttpRequest *request)
 {
     // Hides AccessLogEntry.h from code that does not supply ALE anyway.
@@ -675,41 +678,41 @@
 
             conn->close();
         }
         retryOrBail();
         return;
     }
 
     serverConn = conn;
     flags.connected_okay = true;
 
     debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
 
     comm_add_close_handler(serverConnection()->fd, fwdServerClosedWrapper, this);
 
     if (serverConnection()->getPeer())
         peerConnectSucceded(serverConnection()->getPeer());
 
 #if USE_OPENSSL
     if (!request->flags.pinned) {
         if ((serverConnection()->getPeer() && serverConnection()->getPeer()->use_ssl) ||
-                (!serverConnection()->getPeer() && request->protocol == AnyP::PROTO_HTTPS) ||
+                (!serverConnection()->getPeer() && request->url.getScheme() == AnyP::PROTO_HTTPS) ||
                 request->flags.sslPeek) {
 
             HttpRequest::Pointer requestPointer = request;
             AsyncCall::Pointer callback = asyncCall(17,4,
                 "FwdState::ConnectedToPeer",
                 FwdStatePeerAnswerDialer(&FwdState::connectedToPeer, this));
             Ssl::PeerConnector *connector =
                 new Ssl::PeerConnector(requestPointer, serverConnection(), callback);
             AsyncJob::Start(connector); // will call our callback
             return;
         }
     }
 #endif
 
     dispatch();
 }
 
 #if USE_OPENSSL
 void
 FwdState::connectedToPeer(Ssl::PeerConnectorAnswer &answer)
@@ -929,64 +932,62 @@
 #if USE_OPENSSL
     if (request->flags.sslPeek) {
         CallJobHere1(17, 4, request->clientConnectionManager, ConnStateData,
                      ConnStateData::httpsPeeked, serverConnection());
         unregister(serverConn); // async call owns it now
         complete(); // destroys us
         return;
     }
 #endif
 
     if (serverConnection()->getPeer() != NULL) {
         ++ serverConnection()->getPeer()->stats.fetches;
         request->peer_login = serverConnection()->getPeer()->login;
         request->peer_domain = serverConnection()->getPeer()->domain;
         httpStart(this);
     } else {
         assert(!request->flags.sslPeek);
         request->peer_login = NULL;
         request->peer_domain = NULL;
 
-        switch (request->protocol) {
+        switch (request->url.getScheme()) {
 #if USE_OPENSSL
 
         case AnyP::PROTO_HTTPS:
             httpStart(this);
             break;
 #endif
 
         case AnyP::PROTO_HTTP:
             httpStart(this);
             break;
 
         case AnyP::PROTO_GOPHER:
             gopherStart(this);
             break;
 
         case AnyP::PROTO_FTP:
             ftpStart(this);
             break;
 
         case AnyP::PROTO_CACHE_OBJECT:
 
-        case AnyP::PROTO_INTERNAL:
-
         case AnyP::PROTO_URN:
             fatal_dump("Should never get here");
             break;
 
         case AnyP::PROTO_WHOIS:
             whoisStart(this);
             break;
 
         case AnyP::PROTO_WAIS:	/* Not implemented */
 
         default:
             debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->url() << "'.");
             ErrorState *anErr = new ErrorState(ERR_UNSUP_REQ, Http::scBadRequest, request);
             fail(anErr);
             // Set the dont_retry flag because this is not a transient (network) error.
             flags.dont_retry = true;
             if (Comm::IsConnOpen(serverConn)) {
                 serverConn->close();
             }
             break;

=== modified file 'src/HttpMsg.cc'
--- src/HttpMsg.cc	2013-03-17 12:19:16 +0000
+++ src/HttpMsg.cc	2014-04-25 14:16:28 +0000
@@ -24,41 +24,41 @@
  *  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 "Debug.h"
 #include "HttpHeaderTools.h"
 #include "HttpMsg.h"
 #include "MemBuf.h"
 #include "mime_header.h"
 #include "profiler/Profiler.h"
 #include "SquidConfig.h"
 
 HttpMsg::HttpMsg(http_hdr_owner_type owner): header(owner),
-        cache_control(NULL), hdr_sz(0), content_length(0), protocol(AnyP::PROTO_NONE),
+        cache_control(NULL), hdr_sz(0), content_length(0),
         pstate(psReadyToParseStartLine)
 {}
 
 HttpMsg::~HttpMsg()
 {
     assert(!body_pipe);
 }
 
 HttpMsgParseState &operator++ (HttpMsgParseState &aState)
 {
     int tmp = (int)aState;
     aState = (HttpMsgParseState)(++tmp);
     return aState;
 }
 
 /* find end of headers */
 int
 httpMsgIsolateHeaders(const char **parse_start, int l, const char **blk_start, const char **blk_end)
 {
     /*

=== modified file 'src/HttpMsg.h'
--- src/HttpMsg.h	2013-10-25 00:13:46 +0000
+++ src/HttpMsg.h	2014-04-26 04:31:51 +0000
@@ -50,55 +50,56 @@
 
     virtual void reset() = 0; // will have body when http*Clean()s are gone
 
     void packInto(Packer * p, bool full_uri) const;
 
     ///< produce a message copy, except for a few connection-specific settings
     virtual HttpMsg *clone() const = 0; ///< \todo rename: not a true copy?
 
     /// [re]sets Content-Length header and cached value
     void setContentLength(int64_t clen);
 
     /**
      * \retval true  the message sender asks to keep the connection open.
      * \retval false the message sender will close the connection.
      *
      * Factors other than the headers may result in connection closure.
      */
     bool persistent() const;
 
 public:
+    /**
+     * The HTTP-Version label of this message.
+     */
     Http::ProtocolVersion http_ver;
 
     HttpHeader header;
 
     HttpHdrCc *cache_control;
 
     /* Unsupported, writable, may disappear/change in the future
      * For replies, sums _stored_ status-line, headers, and <CRLF>.
      * Also used to report parsed header size if parse() is successful */
     int hdr_sz;
 
     int64_t content_length;
 
-    AnyP::ProtocolType protocol;
-
     HttpMsgParseState pstate;   /* the current parsing state */
 
     BodyPipe::Pointer body_pipe; // optional pipeline to receive message body
 
     // returns true and sets hdr_sz on success
     // returns false and sets *error to zero when needs more data
     // returns false and sets *error to a positive Http::StatusCode on error
     bool parse(MemBuf *buf, bool eol, Http::StatusCode *error);
 
     bool parseCharBuf(const char *buf, ssize_t end);
 
     int httpMsgParseStep(const char *buf, int len, int atEnd);
 
     virtual int httpMsgParseError();
 
     virtual bool expectingBody(const HttpRequestMethod&, int64_t&) const = 0;
 
     void firstLineBuf(MemBuf&);
 
     virtual bool inheritProperties(const HttpMsg *aMsg) = 0;

=== modified file 'src/HttpReply.cc'
--- src/HttpReply.cc	2013-10-31 19:13:17 +0000
+++ src/HttpReply.cc	2014-04-25 14:23:01 +0000
@@ -587,41 +587,40 @@
             debugs(58, 4, HERE << "bodySizeMax=" << bodySizeMax);
             bodySizeMax = l->size; // may be -1
             break;
         }
     }
 }
 
 // XXX: check that this is sufficient for eCAP cloning
 HttpReply *
 HttpReply::clone() const
 {
     HttpReply *rep = new HttpReply();
     rep->sline = sline; // used in hdrCacheInit() call below
     rep->header.append(&header);
     rep->hdrCacheInit();
     rep->hdr_sz = hdr_sz;
     rep->http_ver = http_ver;
     rep->pstate = pstate;
     rep->body_pipe = body_pipe;
 
-    rep->protocol = protocol;
     // keep_alive is handled in hdrCacheInit()
     return rep;
 }
 
 bool HttpReply::inheritProperties(const HttpMsg *aMsg)
 {
     const HttpReply *aRep = dynamic_cast<const HttpReply*>(aMsg);
     if (!aRep)
         return false;
     keep_alive = aRep->keep_alive;
     return true;
 }
 
 void HttpReply::removeStaleWarnings()
 {
     String warning;
     if (header.getList(HDR_WARNING, &warning)) {
         const String newWarning = removeStaleWarningValues(warning);
         if (warning.size() && warning.size() == newWarning.size())
             return; // some warnings are there and none changed

=== modified file 'src/HttpRequest.cc'
--- src/HttpRequest.cc	2014-04-22 02:47:09 +0000
+++ src/HttpRequest.cc	2014-04-26 05:14:55 +0000
@@ -65,49 +65,49 @@
 
 HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) :
         HttpMsg(hoRequest)
 {
     static unsigned int id = 1;
     debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id);
     init();
     initHTTP(aMethod, aProtocol, aUrlpath);
 }
 
 HttpRequest::~HttpRequest()
 {
     clean();
     debugs(93,7, HERE << "destructed, this=" << this);
 }
 
 void
 HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath)
 {
     method = aMethod;
-    protocol = aProtocol;
+    url.makeScheme(aProtocol);
     urlpath = aUrlpath;
 }
 
 void
 HttpRequest::init()
 {
     method = Http::METHOD_NONE;
-    protocol = AnyP::PROTO_NONE;
+    url.clear();
     urlpath = NULL;
     login[0] = '\0';
     host[0] = '\0';
     host_is_numeric = -1;
 #if USE_AUTH
     auth_user_request = NULL;
 #endif
     port = 0;
     canonical = NULL;
     memset(&flags, '\0', sizeof(flags));
     range = NULL;
     ims = -1;
     imslen = 0;
     lastmod = -1;
     client_addr.setEmpty();
     my_addr.setEmpty();
     body_pipe = NULL;
     // hier
     dnsWait = -1;
     errType = ERR_NONE;
@@ -133,40 +133,41 @@
 #endif
 #if ICAP_CLIENT
     icapHistory_ = NULL;
 #endif
     rangeOffsetLimit = -2; //a value of -2 means not checked yet
 }
 
 void
 HttpRequest::clean()
 {
     // we used to assert that the pipe is NULL, but now the request only
     // points to a pipe that is owned and initiated by another object.
     body_pipe = NULL;
 #if USE_AUTH
     auth_user_request = NULL;
 #endif
     safe_free(canonical);
 
     safe_free(vary_headers);
 
+    url.clear();
     urlpath.clean();
 
     header.clean();
 
     if (cache_control) {
         delete cache_control;
         cache_control = NULL;
     }
 
     if (range) {
         delete range;
         range = NULL;
     }
 
     myportname.clean();
 
     notes = NULL;
 
     tag.clean();
 #if USE_AUTH
@@ -180,41 +181,41 @@
     etag.clean();
 
 #if USE_ADAPTATION
     adaptHistory_ = NULL;
 #endif
 #if ICAP_CLIENT
     icapHistory_ = NULL;
 #endif
 }
 
 void
 HttpRequest::reset()
 {
     clean();
     init();
 }
 
 HttpRequest *
 HttpRequest::clone() const
 {
-    HttpRequest *copy = new HttpRequest(method, protocol, urlpath.termedBuf());
+    HttpRequest *copy = new HttpRequest(method, url.getScheme(), urlpath.termedBuf());
     // TODO: move common cloning clone to Msg::copyTo() or copy ctor
     copy->header.append(&header);
     copy->hdrCacheInit();
     copy->hdr_sz = hdr_sz;
     copy->http_ver = http_ver;
     copy->pstate = pstate; // TODO: should we assert a specific state here?
     copy->body_pipe = body_pipe;
 
     strncpy(copy->login, login, sizeof(login)); // MAX_LOGIN_SZ
     strncpy(copy->host, host, sizeof(host)); // SQUIDHOSTNAMELEN
     copy->host_addr = host_addr;
 
     copy->port = port;
     // urlPath handled in ctor
     copy->canonical = canonical ? xstrdup(canonical) : NULL;
 
     // range handled in hdrCacheInit()
     copy->ims = ims;
     copy->imslen = imslen;
     copy->hier = hier; // Is it safe to copy? Should we?
@@ -577,41 +578,41 @@
 HttpRequest *
 HttpRequest::CreateFromUrl(char * url)
 {
     return urlParse(Http::METHOD_GET, url, NULL);
 }
 
 /**
  * Are responses to this request possible cacheable ?
  * If false then no matter what the response must not be cached.
  */
 bool
 HttpRequest::maybeCacheable()
 {
     // Intercepted request with Host: header which cannot be trusted.
     // Because it failed verification, or someone bypassed the security tests
     // we cannot cache the reponse for sharing between clients.
     // TODO: update cache to store for particular clients only (going to same Host: and destination IP)
     if (!flags.hostVerified && (flags.intercepted || flags.interceptTproxy))
         return false;
 
-    switch (protocol) {
+    switch (url.getScheme()) {
     case AnyP::PROTO_HTTP:
     case AnyP::PROTO_HTTPS:
         if (!method.respMaybeCacheable())
             return false;
 
         // XXX: this would seem the correct place to detect request cache-controls
         //      no-store, private and related which block cacheability
         break;
 
     case AnyP::PROTO_GOPHER:
         if (!gopherCachable(this))
             return false;
         break;
 
     case AnyP::PROTO_CACHE_OBJECT:
         return false;
 
         //case AnyP::PROTO_FTP:
     default:
         break;

=== modified file 'src/HttpRequest.h'
--- src/HttpRequest.h	2014-03-15 02:50:12 +0000
+++ src/HttpRequest.h	2014-04-25 10:35:02 +0000
@@ -22,40 +22,41 @@
  *  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.
  *
  */
 
 #ifndef SQUID_HTTPREQUEST_H
 #define SQUID_HTTPREQUEST_H
 
 #include "base/CbcPointer.h"
 #include "Debug.h"
 #include "err_type.h"
 #include "HierarchyLogEntry.h"
 #include "HttpMsg.h"
 #include "HttpRequestMethod.h"
 #include "Notes.h"
 #include "RequestFlags.h"
+#include "URL.h"
 
 #if USE_AUTH
 #include "auth/UserRequest.h"
 #endif
 #if USE_ADAPTATION
 #include "adaptation/History.h"
 #endif
 #if ICAP_CLIENT
 #include "adaptation/icap/History.h"
 #endif
 #if USE_SQUID_EUI
 #include "eui/Eui48.h"
 #include "eui/Eui64.h"
 #endif
 
 class ConnStateData;
 
 /*  Http Request */
 void httpRequestPack(void *obj, Packer *p);
 
@@ -119,40 +120,43 @@
 #if ICAP_CLIENT
     /// Returns possibly nil history, creating it if icap logging is enabled
     Adaptation::Icap::History::Pointer icapHistory() const;
 #endif
 
     void recordLookup(const DnsLookupDetails &detail);
 
     /// sets error detail if no earlier detail was available
     void detailError(err_type aType, int aDetail);
     /// clear error details, useful for retries/repeats
     void clearError();
 
 protected:
     void clean();
 
     void init();
 
 public:
     HttpRequestMethod method;
 
+    // TODO expand to include all URI parts
+    URL url; ///< the request URI (scheme only)
+
     char login[MAX_LOGIN_SZ];
 
 private:
     char host[SQUIDHOSTNAMELEN];
     int host_is_numeric;
 
 #if USE_ADAPTATION
     mutable Adaptation::History::Pointer adaptHistory_; ///< per-HTTP transaction info
 #endif
 #if ICAP_CLIENT
     mutable Adaptation::Icap::History::Pointer icapHistory_; ///< per-HTTP transaction info
 #endif
 
 public:
     Ip::Address host_addr;
 #if USE_AUTH
     Auth::UserRequest::Pointer auth_user_request;
 #endif
     unsigned short port;
 

=== modified file 'src/URL.h'
--- src/URL.h	2014-02-07 13:45:20 +0000
+++ src/URL.h	2014-04-26 05:17:43 +0000
@@ -28,64 +28,72 @@
  *
  */
 
 #ifndef SQUID_SRC_URL_H
 #define SQUID_SRC_URL_H
 
 #include "anyp/UriScheme.h"
 #include "MemPool.h"
 
 /**
  \ingroup POD
  *
  * The URL class represents a Uniform Resource Location
  */
 class URL
 {
 public:
     MEMPROXY_CLASS(URL);
     URL() : scheme_() {}
     URL(AnyP::UriScheme const &aScheme) : scheme_(aScheme) {}
+
+    void clear() {
+        scheme_=AnyP::PROTO_NONE;
+    }
+
     AnyP::UriScheme const & getScheme() const {return scheme_;}
 
+    /// convert the URL scheme to that given
+    void makeScheme(const AnyP::ProtocolType &p) {scheme_=p;}
+
 private:
     /**
      \par
      * The scheme of this URL. This has the 'type code' smell about it.
      * In future we may want to make the methods that dispatch based on
      * the scheme virtual and have a class per protocol.
      \par
      * On the other hand, having Protocol as an explicit concept is useful,
      * see for instance the ACLProtocol acl type. One way to represent this
      * is to have one prototype URL with no host etc for each scheme,
      * another is to have an explicit scheme class, and then each URL class
      * could be a subclass of the scheme. Another way is one instance of
      * a AnyP::UriScheme class instance for each URL scheme we support, and one URL
      * class for each manner of treating the scheme : a Hierarchical URL, a
      * non-hierarchical URL etc.
      \par
      * Deferring the decision, its a type code for now. RBC 20060507.
      \par
      * In order to make taking any of these routes easy, scheme is private
      * and immutable, only settable at construction time,
      */
-    AnyP::UriScheme const scheme_;
+    AnyP::UriScheme scheme_;
 };
 
 MEMPROXY_CLASS_INLINE(URL);
 
 class HttpRequest;
 class HttpRequestMethod;
 
 AnyP::ProtocolType urlParseProtocol(const char *, const char *e = NULL);
 void urlInitialize(void);
 HttpRequest *urlParse(const HttpRequestMethod&, char *, HttpRequest *request = NULL);
 const char *urlCanonical(HttpRequest *);
 char *urlCanonicalClean(const HttpRequest *);
 const char *urlCanonicalFakeHttps(const HttpRequest * request);
 bool urlIsRelative(const char *);
 char *urlMakeAbsolute(const HttpRequest *, const char *);
 char *urlRInternal(const char *host, unsigned short port, const char *dir, const char *name);
 char *urlInternal(const char *dir, const char *name);
 int matchDomainName(const char *host, const char *domain);
 int urlCheckRequest(const HttpRequest *);
 int urlDefaultPort(AnyP::ProtocolType p);

=== modified file 'src/acl/Protocol.cc'
--- src/acl/Protocol.cc	2013-10-25 00:13:46 +0000
+++ src/acl/Protocol.cc	2014-04-25 15:26:01 +0000
@@ -25,32 +25,32 @@
  *
  *  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.
  *
  *
  * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
  */
 
 #include "squid.h"
 #include "acl/Checklist.h"
 #include "acl/Protocol.h"
 #include "acl/ProtocolData.h"
 #include "HttpRequest.h"
 
 /* explicit template instantiation required for some systems */
 
 template class ACLStrategised<AnyP::ProtocolType>;
 
 int
-ACLProtocolStrategy::match (ACLData<MatchType> * &data, ACLFilledChecklist *checklist, ACLFlags &)
+ACLProtocolStrategy::match(ACLData<MatchType> * &data, ACLFilledChecklist *checklist, ACLFlags &)
 {
-    return data->match (checklist->request->protocol);
+    return data->match(checklist->request->url.getScheme());
 }
 
 ACLProtocolStrategy *
 ACLProtocolStrategy::Instance()
 {
     return &Instance_;
 }
 
 ACLProtocolStrategy ACLProtocolStrategy::Instance_;

=== modified file 'src/adaptation/ecap/Host.cc'
--- src/adaptation/ecap/Host.cc	2014-02-08 13:36:42 +0000
+++ src/adaptation/ecap/Host.cc	2014-04-26 05:21:34 +0000
@@ -28,41 +28,40 @@
 
 Adaptation::Ecap::Host::Host()
 {
     // assign our host-specific IDs to well-known names
     // this code can run only once
 
     libecap::headerTransferEncoding.assignHostId(HDR_TRANSFER_ENCODING);
     libecap::headerReferer.assignHostId(HDR_REFERER);
     libecap::headerContentLength.assignHostId(HDR_CONTENT_LENGTH);
     libecap::headerVia.assignHostId(HDR_VIA);
     // TODO: libecap::headerXClientIp.assignHostId(HDR_X_CLIENT_IP);
     // TODO: libecap::headerXServerIp.assignHostId(HDR_X_SERVER_IP);
 
     libecap::protocolHttp.assignHostId(AnyP::PROTO_HTTP);
     libecap::protocolHttps.assignHostId(AnyP::PROTO_HTTPS);
     libecap::protocolFtp.assignHostId(AnyP::PROTO_FTP);
     libecap::protocolGopher.assignHostId(AnyP::PROTO_GOPHER);
     libecap::protocolWais.assignHostId(AnyP::PROTO_WAIS);
     libecap::protocolUrn.assignHostId(AnyP::PROTO_URN);
     libecap::protocolWhois.assignHostId(AnyP::PROTO_WHOIS);
-    protocolInternal.assignHostId(AnyP::PROTO_INTERNAL);
     protocolCacheObj.assignHostId(AnyP::PROTO_CACHE_OBJECT);
     protocolIcp.assignHostId(AnyP::PROTO_ICP);
 #if USE_HTCP
     protocolHtcp.assignHostId(AnyP::PROTO_HTCP);
 #endif
     protocolIcy.assignHostId(AnyP::PROTO_ICY);
     protocolUnknown.assignHostId(AnyP::PROTO_UNKNOWN);
 
     // allows adapter to safely ignore this in adapter::Service::configure()
     metaBypassable.assignHostId(1);
 }
 
 std::string
 Adaptation::Ecap::Host::uri() const
 {
     return "ecap://squid-cache.org/ecap/hosts/squid";
 }
 
 void
 Adaptation::Ecap::Host::describe(std::ostream &os) const

=== modified file 'src/adaptation/ecap/MessageRep.cc'
--- src/adaptation/ecap/MessageRep.cc	2014-04-25 13:37:10 +0000
+++ src/adaptation/ecap/MessageRep.cc	2014-04-26 05:21:39 +0000
@@ -141,42 +141,40 @@
     case AnyP::PROTO_HTTPS:
         return libecap::protocolHttps;
     case AnyP::PROTO_FTP:
         return libecap::protocolFtp;
     case AnyP::PROTO_GOPHER:
         return libecap::protocolGopher;
     case AnyP::PROTO_WAIS:
         return libecap::protocolWais;
     case AnyP::PROTO_WHOIS:
         return libecap::protocolWhois;
     case AnyP::PROTO_URN:
         return libecap::protocolUrn;
     case AnyP::PROTO_ICP:
         return protocolIcp;
 #if USE_HTCP
     case AnyP::PROTO_HTCP:
         return protocolHtcp;
 #endif
     case AnyP::PROTO_CACHE_OBJECT:
         return protocolCacheObj;
-    case AnyP::PROTO_INTERNAL:
-        return protocolInternal;
     case AnyP::PROTO_ICY:
         return protocolIcy;
     case AnyP::PROTO_COAP:
     case AnyP::PROTO_COAPS: // use 'unknown' until libecap supports coap:// and coaps://
     case AnyP::PROTO_UNKNOWN:
         return protocolUnknown; // until we remember the protocol image
     case AnyP::PROTO_NONE:
         return Name();
 
     case AnyP::PROTO_MAX:
         break; // should not happen
         // no default to catch AnyP::PROTO_ additions
     }
     Must(false); // not reached
     return Name();
 }
 
 void
 Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
 {

=== modified file 'src/anyp/ProtocolType.h'
--- src/anyp/ProtocolType.h	2014-02-21 10:46:19 +0000
+++ src/anyp/ProtocolType.h	2014-04-26 05:22:14 +0000
@@ -10,41 +10,40 @@
  * List of all protocols known and supported.
  * This is a combined list. It is used as type-codes where needed and
  * the AnyP::ProtocolType_Str array of strings may be used for display
  */
 typedef enum {
     PROTO_NONE = 0,
     PROTO_HTTP,
     PROTO_FTP,
     PROTO_HTTPS,
     PROTO_COAP,
     PROTO_COAPS,
     PROTO_GOPHER,
     PROTO_WAIS,
     PROTO_CACHE_OBJECT,
     PROTO_ICP,
 #if USE_HTCP
     PROTO_HTCP,
 #endif
     PROTO_URN,
     PROTO_WHOIS,
-    PROTO_INTERNAL,
     PROTO_ICY,
     PROTO_UNKNOWN,
     PROTO_MAX
 } ProtocolType;
 
 extern const char *ProtocolType_str[];
 
 /** Display the registered Protocol Type (in upper case).
  *  If the protocol is not a registered AnyP::ProtocolType nothing will be displayed.
  * The caller is responsible for any alternative text.
  */
 inline std::ostream &
 operator <<(std::ostream &os, ProtocolType const &p)
 {
     if (PROTO_NONE <= p && p < PROTO_MAX)
         os << ProtocolType_str[p];
     else
         os << static_cast<int>(p);
     return os;
 }

=== modified file 'src/carp.cc'
--- src/carp.cc	2014-04-25 10:47:59 +0000
+++ src/carp.cc	2014-04-25 12:16:28 +0000
@@ -174,43 +174,41 @@
     CachePeer *tp;
     unsigned int user_hash = 0;
     unsigned int combined_hash;
     double score;
     double high_score = 0;
 
     if (n_carp_peers == 0)
         return NULL;
 
     /* calculate hash key */
     debugs(39, 2, "carpSelectParent: Calculating hash for " << urlCanonical(request));
 
     /* select CachePeer */
     for (k = 0; k < n_carp_peers; ++k) {
         SBuf key;
         tp = carp_peers[k];
         if (tp->options.carp_key.set) {
             //this code follows urlCanonical's pattern.
             //   corner cases should use the canonical URL
             if (tp->options.carp_key.scheme) {
-                // temporary, until bug 1961 URL handling is fixed.
-                const AnyP::UriScheme sch(request->protocol);
-                key.append(sch.c_str());
+                key.append(request->url.getScheme().c_str());
                 if (key.length()) //if the scheme is not empty
                     key.append("://");
             }
             if (tp->options.carp_key.host) {
                 key.append(request->GetHost());
             }
             if (tp->options.carp_key.port) {
                 static char portbuf[7];
                 snprintf(portbuf,7,":%d", request->port);
                 key.append(portbuf);
             }
             if (tp->options.carp_key.path) {
                 String::size_type pos;
                 if ((pos=request->urlpath.find('?'))!=String::npos)
                     key.append(SBuf(request->urlpath.substr(0,pos)));
                 else
                     key.append(SBuf(request->urlpath));
             }
             if (tp->options.carp_key.params) {
                 String::size_type pos;

=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2014-04-22 16:01:23 +0000
+++ src/cf.data.pre	2014-04-25 13:50:51 +0000
@@ -712,41 +712,41 @@
 			capable of processing more than one query at a time.
 	  cache=n	limit the result cache size, default is unbounded.
 	  grace=n	Percentage remaining of TTL where a refresh of a
 			cached entry should be initiated without needing to
 			wait for a new reply. (default is for no grace period)
 	  protocol=2.5	Compatibility mode for Squid-2.5 external acl helpers
 	  ipv4 / ipv6	IP protocol used to communicate with this helper.
 			The default is to auto-detect IPv6 and use it when available.
 
 	FORMAT specifications
 
 	  %LOGIN	Authenticated user login name
 	  %EXT_USER	Username from previous external acl
 	  %EXT_LOG	Log details from previous external acl
 	  %EXT_TAG	Tag from previous external acl
 	  %IDENT	Ident user name
 	  %SRC		Client IP
 	  %SRCPORT	Client source port
 	  %URI		Requested URI
 	  %DST		Requested host
-	  %PROTO	Requested protocol
+	  %PROTO	Requested URL scheme (protocol)
 	  %PORT		Requested port
 	  %PATH		Requested URL path
 	  %METHOD	Request method
 	  %MYADDR	Squid interface address
 	  %MYPORT	Squid http_port number
 	  %PATH		Requested URL-path (including query-string if any)
 	  %USER_CERT	SSL User certificate in PEM format
 	  %USER_CERTCHAIN SSL User certificate chain in PEM format
 	  %USER_CERT_xx	SSL User certificate subject attribute xx
 	  %USER_CA_xx	SSL User certificate issuer attribute xx
 
 	  %>{Header}	HTTP request header "Header"
 	  %>{Hdr:member}
 	  		HTTP request header "Hdr" list member "member"
 	  %>{Hdr:;member}
 	  		HTTP request header list member using ; as
 	  		list separator. ; can be any non-alphanumeric
 			character.
 
 	  %<{Header}	HTTP reply header "Header"

=== modified file 'src/client_side.cc'
--- src/client_side.cc	2014-04-22 12:51:21 +0000
+++ src/client_side.cc	2014-04-26 05:35:21 +0000
@@ -2703,54 +2703,57 @@
 
     /** \par
      * If transparent or interception mode is working clone the transparent and interception flags
      * from the port settings to the request.
      */
     if (http->clientConnection != NULL) {
         request->flags.intercepted = ((http->clientConnection->flags & COMM_INTERCEPTION) != 0);
         request->flags.interceptTproxy = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
         if (request->flags.interceptTproxy) {
             if (Config.accessList.spoof_client_ip) {
                 ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.spoof_client_ip, http);
                 request->flags.spoofClientIp = (checklist->fastCheck() == ACCESS_ALLOWED);
                 delete checklist;
             } else
                 request->flags.spoofClientIp = true;
         } else
             request->flags.spoofClientIp = false;
     }
 
     if (internalCheck(request->urlpath.termedBuf())) {
-        if (internalHostnameIs(request->GetHost()) &&
-                request->port == getMyPort()) {
+        if (internalHostnameIs(request->GetHost()) && request->port == getMyPort()) {
+            debugs(33, 2, "internal URL found: " << request->url.getScheme() << "://" << request->GetHost() <<
+                   ':' << request->port);
             http->flags.internal = true;
         } else if (Config.onoff.global_internal_static && internalStaticCheck(request->urlpath.termedBuf())) {
+            debugs(33, 2, "internal URL found: " << request->url.getScheme() << "://" << request->GetHost() <<
+                   ':' << request->port << " (global_internal_static on)");
             request->SetHost(internalHostname());
             request->port = getMyPort();
             http->flags.internal = true;
-        }
+        } else
+            debugs(33, 2, "internal URL found: " << request->url.getScheme() << "://" << request->GetHost() <<
+                   ':' << request->port << " (not this proxy)");
     }
 
-    if (http->flags.internal) {
-        request->protocol = AnyP::PROTO_HTTP;
+    if (http->flags.internal)
         request->login[0] = '\0';
-    }
 
     request->flags.internal = http->flags.internal;
     setLogUri (http, urlCanonicalClean(request.getRaw()));
     request->client_addr = conn->clientConnection->remote; // XXX: remove reuest->client_addr member.
 #if FOLLOW_X_FORWARDED_FOR
     // indirect client gets stored here because it is an HTTP header result (from X-Forwarded-For:)
     // not a details about teh TCP connection itself
     request->indirect_client_addr = conn->clientConnection->remote;
 #endif /* FOLLOW_X_FORWARDED_FOR */
     request->my_addr = conn->clientConnection->local;
     request->myportname = conn->port->name;
     request->http_ver = http_ver;
 
     // Link this HttpRequest to ConnStateData relatively early so the following complex handling can use it
     // TODO: this effectively obsoletes a lot of conn->FOO copying. That needs cleaning up later.
     request->clientConnectionManager = conn;
 
     if (request->header.chunked()) {
         chunked = true;
     } else if (request->header.has(HDR_TRANSFER_ENCODING)) {

=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc	2014-04-22 02:47:09 +0000
+++ src/client_side_reply.cc	2014-04-25 14:07:52 +0000
@@ -566,41 +566,41 @@
          * both have a stale version of the object.
          */
         r->flags.needValidation = true;
 
         if (e->lastmod < 0) {
             debugs(88, 3, "validate HIT object? NO. Missing Last-Modified header. Do MISS.");
             /*
              * Previous reply didn't have a Last-Modified header,
              * we cannot revalidate it.
              */
             http->logType = LOG_TCP_MISS;
             processMiss();
         } else if (r->flags.noCache) {
             debugs(88, 3, "validate HIT object? NO. Client sent CC:no-cache. Do CLIENT_REFRESH_MISS");
             /*
              * This did not match a refresh pattern that overrides no-cache
              * we should honour the client no-cache header.
              */
             http->logType = LOG_TCP_CLIENT_REFRESH_MISS;
             processMiss();
-        } else if (r->protocol == AnyP::PROTO_HTTP) {
+        } else if (r->url.getScheme() == AnyP::PROTO_HTTP) {
             debugs(88, 3, "validate HIT object? YES.");
             /*
              * Object needs to be revalidated
              * XXX This could apply to FTP as well, if Last-Modified is known.
              */
             processExpired();
         } else {
             debugs(88, 3, "validate HIT object? NO. Client protocol non-HTTP. Do MISS.");
             /*
              * We don't know how to re-validate other protocols. Handle
              * them as if the object has expired.
              */
             http->logType = LOG_TCP_MISS;
             processMiss();
         }
     } else if (r->conditional()) {
         debugs(88, 5, "conditional HIT");
         processConditional(result);
     } else {
         /*
@@ -670,44 +670,40 @@
         err = clientBuildError(ERR_ACCESS_DENIED, Http::scForbidden, NULL, http->getConn()->clientConnection->remote, http->request);
         createStoreEntry(r->method, RequestFlags());
         errorAppendEntry(http->storeEntry(), err);
         triggerInitialStoreRead();
         return;
     } else {
         assert(http->out.offset == 0);
         createStoreEntry(r->method, r->flags);
         triggerInitialStoreRead();
 
         if (http->redirect.status) {
             HttpReply *rep = new HttpReply;
             http->logType = LOG_TCP_REDIRECT;
             http->storeEntry()->releaseRequest();
             rep->redirect(http->redirect.status, http->redirect.location);
             http->storeEntry()->replaceHttpReply(rep);
             http->storeEntry()->complete();
             return;
         }
 
-        /** Check for internal requests. Update Protocol info if so. */
-        if (http->flags.internal)
-            r->protocol = AnyP::PROTO_INTERNAL;
-
         assert(r->clientConnectionManager == http->getConn());
 
         /** Start forwarding to get the new object from network */
         Comm::ConnectionPointer conn = http->getConn() != NULL ? http->getConn()->clientConnection : NULL;
         FwdState::Start(conn, http->storeEntry(), r, http->al);
     }
 }
 
 /**
  * client issued a request with an only-if-cached cache-control directive;
  * we did not find a cached object that can be returned without
  *     contacting other servers;
  * respond with a 504 (Gateway Timeout) as suggested in [RFC 2068]
  */
 void
 clientReplyContext::processOnlyIfCachedMiss()
 {
     debugs(88, 4, http->request->method << ' ' << http->uri);
     http->al->http.code = Http::scGatewayTimeout;
     ErrorState *err = clientBuildError(ERR_ONLY_IF_CACHED_MISS, Http::scGatewayTimeout, NULL,

=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc	2014-04-22 02:47:09 +0000
+++ src/client_side_request.cc	2014-04-26 05:35:57 +0000
@@ -661,44 +661,44 @@
             // XXX: match the scheme default port against the apparent destination
 
             // verify the destination DNS is one of the Host: headers IPs
             ipcache_nbgethostbyname(host, hostHeaderIpVerifyWrapper, this);
         }
     } else if (!Config.onoff.hostStrictVerify) {
         debugs(85, 3, HERE << "validate skipped.");
         http->doCallouts();
     } else if (strlen(host) != strlen(http->request->GetHost())) {
         // Verify forward-proxy requested URL domain matches the Host: header
         debugs(85, 3, HERE << "FAIL on validate URL domain length " << http->request->GetHost() << " matches Host: " << host);
         hostHeaderVerifyFailed(host, http->request->GetHost());
     } else if (matchDomainName(host, http->request->GetHost()) != 0) {
         // Verify forward-proxy requested URL domain matches the Host: header
         debugs(85, 3, HERE << "FAIL on validate URL domain " << http->request->GetHost() << " matches Host: " << host);
         hostHeaderVerifyFailed(host, http->request->GetHost());
     } else if (portStr && port != http->request->port) {
         // Verify forward-proxy requested URL domain matches the Host: header
         debugs(85, 3, HERE << "FAIL on validate URL port " << http->request->port << " matches Host: port " << portStr);
         hostHeaderVerifyFailed("URL port", portStr);
-    } else if (!portStr && http->request->method != Http::METHOD_CONNECT && http->request->port != urlDefaultPort(http->request->protocol)) {
+    } else if (!portStr && http->request->method != Http::METHOD_CONNECT && http->request->port != urlDefaultPort(http->request->url.getScheme())) {
         // Verify forward-proxy requested URL domain matches the Host: header
         // Special case: we don't have a default-port to check for CONNECT. Assume URL is correct.
-        debugs(85, 3, HERE << "FAIL on validate URL port " << http->request->port << " matches Host: default port " << urlDefaultPort(http->request->protocol));
+        debugs(85, 3, "FAIL on validate URL port " << http->request->port << " matches Host: default port " << urlDefaultPort(http->request->url.getScheme()));
         hostHeaderVerifyFailed("URL port", "default port");
     } else {
         // Okay no problem.
         debugs(85, 3, HERE << "validate passed.");
         http->request->flags.hostVerified = true;
         http->doCallouts();
     }
     safe_free(hostB);
 }
 
 /* This is the entry point for external users of the client_side routines */
 void
 ClientRequestContext::clientAccessCheck()
 {
 #if FOLLOW_X_FORWARDED_FOR
     if (!http->request->flags.doneFollowXff() &&
             Config.accessList.followXFF &&
             http->request->header.has(HDR_X_FORWARDED_FOR)) {
 
         /* we always trust the direct client address for actual use */
@@ -966,47 +966,47 @@
      * This is incorrect: authenticating requests can be sent via a hierarchy
      * (they can even be cached if the correct headers are set on the reply)
      */
     if (request->flags.auth)
         return 0;
 
     if (method == Http::METHOD_TRACE)
         return 1;
 
     if (method != Http::METHOD_GET)
         return 0;
 
     /* scan hierarchy_stoplist */
     for (p = Config.hierarchy_stoplist; p; p = p->next)
         if (strstr(url, p->key))
             return 0;
 
     if (request->flags.loopDetected)
         return 0;
 
-    if (request->protocol == AnyP::PROTO_HTTP)
+    if (request->url.getScheme() == AnyP::PROTO_HTTP)
         return method.respMaybeCacheable();
 
-    if (request->protocol == AnyP::PROTO_GOPHER)
+    if (request->url.getScheme() == AnyP::PROTO_GOPHER)
         return gopherCachable(request);
 
-    if (request->protocol == AnyP::PROTO_CACHE_OBJECT)
+    if (request->url.getScheme() == AnyP::PROTO_CACHE_OBJECT)
         return 0;
 
     return 1;
 }
 
 static void
 clientCheckPinning(ClientHttpRequest * http)
 {
     HttpRequest *request = http->request;
     HttpHeader *req_hdr = &request->header;
     ConnStateData *http_conn = http->getConn();
 
     /* Internal requests such as those from ESI includes may be without
      * a client connection
      */
     if (!http_conn)
         return;
 
     request->flags.connectionAuthDisabled = http_conn->port->connection_auth_disabled;
     if (!request->flags.connectionAuthDisabled) {

=== modified file 'src/errorpage.cc'
--- src/errorpage.cc	2014-04-25 13:38:22 +0000
+++ src/errorpage.cc	2014-04-25 15:36:19 +0000
@@ -955,41 +955,41 @@
         } else if (!building_deny_info_url)
             p = "[unknown method]";
         break;
 
     case 'o':
         p = request ? request->extacl_message.termedBuf() : external_acl_message;
         if (!p && !building_deny_info_url)
             p = "[not available]";
         break;
 
     case 'p':
         if (request) {
             mb.Printf("%d", (int) request->port);
         } else if (!building_deny_info_url) {
             p = "[unknown port]";
         }
         break;
 
     case 'P':
         if (request) {
-            p = AnyP::ProtocolType_str[request->protocol];
+            p = request->url.getScheme().c_str();
         } else if (!building_deny_info_url) {
             p = "[unknown protocol]";
         }
         break;
 
     case 'R':
         if (building_deny_info_url) {
             p = (request->urlpath.size() != 0 ? request->urlpath.termedBuf() : "/");
             no_urlescape = 1;
             break;
         }
         if (NULL != request) {
             Packer pck;
             String urlpath_or_slash;
 
             if (request->urlpath.size() != 0)
                 urlpath_or_slash = request->urlpath;
             else
                 urlpath_or_slash = "/";
 

=== modified file 'src/external_acl.cc'
--- src/external_acl.cc	2014-04-22 02:47:09 +0000
+++ src/external_acl.cc	2014-04-25 13:53:28 +0000
@@ -1028,41 +1028,41 @@
 #endif
 
         case _external_acl_format::EXT_ACL_MYADDR:
             str = request->my_addr.toStr(buf, sizeof(buf));
             break;
 
         case _external_acl_format::EXT_ACL_MYPORT:
             snprintf(buf, sizeof(buf), "%d", request->my_addr.port());
             str = buf;
             break;
 
         case _external_acl_format::EXT_ACL_URI:
             str = urlCanonical(request);
             break;
 
         case _external_acl_format::EXT_ACL_DST:
             str = request->GetHost();
             break;
 
         case _external_acl_format::EXT_ACL_PROTO:
-            str = AnyP::ProtocolType_str[request->protocol];
+            str = request->url.getScheme().c_str();
             break;
 
         case _external_acl_format::EXT_ACL_PORT:
             snprintf(buf, sizeof(buf), "%d", request->port);
             str = buf;
             break;
 
         case _external_acl_format::EXT_ACL_PATH:
             str = request->urlpath.termedBuf();
             break;
 
         case _external_acl_format::EXT_ACL_METHOD:
             {
                 const SBuf &s = request->method.image();
                 sb.append(s.rawContent(), s.length());
             }
             str = sb.termedBuf();
             break;
 
         case _external_acl_format::EXT_ACL_HEADER_REQUEST:

=== modified file 'src/ftp.cc'
--- src/ftp.cc	2014-04-04 16:36:47 +0000
+++ src/ftp.cc	2014-04-25 13:55:20 +0000
@@ -3715,41 +3715,41 @@
     return newrep;
 }
 
 /**
  \ingroup ServerProtocolFTPAPI
  \todo Should be a URL class API call.
  *
  *  Construct an URI with leading / in PATH portion for use by CWD command
  *  possibly others. FTP encodes absolute paths as beginning with '/'
  *  after the initial URI path delimiter, which happens to be / itself.
  *  This makes FTP absolute URI appear as:  ftp:host:port//root/path
  *  To encompass older software which compacts multiple // to / in transit
  *  We use standard URI-encoding on the second / making it
  *  ftp:host:port/%2froot/path  AKA 'the FTP %2f hack'.
  */
 const char *
 ftpUrlWith2f(HttpRequest * request)
 {
     String newbuf = "%2f";
 
-    if (request->protocol != AnyP::PROTO_FTP)
+    if (request->url.getScheme() != AnyP::PROTO_FTP)
         return NULL;
 
     if ( request->urlpath[0]=='/' ) {
         newbuf.append(request->urlpath);
         request->urlpath.absorb(newbuf);
         safe_free(request->canonical);
     } else if ( !strncmp(request->urlpath.termedBuf(), "%2f", 3) ) {
         newbuf.append(request->urlpath.substr(1,request->urlpath.size()));
         request->urlpath.absorb(newbuf);
         safe_free(request->canonical);
     }
 
     return urlCanonical(request);
 }
 
 void
 FtpStateData::printfReplyBody(const char *fmt, ...)
 {
     va_list args;
     va_start (args, fmt);

=== modified file 'src/http.cc'
--- src/http.cc	2014-04-22 02:47:09 +0000
+++ src/http.cc	2014-04-25 14:15:43 +0000
@@ -1790,41 +1790,41 @@
             /** If set to OFF - append 'unknown'. */
             strListAdd(&strFwd, "unknown", ',');
         } else if (strcmp(opt_forwarded_for, "transparent") == 0) {
             /** If set to TRANSPARENT - pass through unchanged. */
         } else if (strcmp(opt_forwarded_for, "truncate") == 0) {
             /** If set to TRUNCATE - drop existing list and replace with client IP or 'unknown'. */
             if ( request->client_addr.isNoAddr() )
                 strFwd = "unknown";
             else
                 strFwd = request->client_addr.toStr(ntoabuf, MAX_IPSTRLEN);
         }
         if (strFwd.size() > 0)
             hdr_out->putStr(HDR_X_FORWARDED_FOR, strFwd.termedBuf());
     }
     /** If set to DELETE - do not copy through. */
 
     /* append Host if not there already */
     if (!hdr_out->has(HDR_HOST)) {
         if (request->peer_domain) {
             hdr_out->putStr(HDR_HOST, request->peer_domain);
-        } else if (request->port == urlDefaultPort(request->protocol)) {
+        } else if (request->port == urlDefaultPort(request->url.getScheme())) {
             /* use port# only if not default */
             hdr_out->putStr(HDR_HOST, request->GetHost());
         } else {
             httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
                               request->GetHost(),
                               (int) request->port);
         }
     }
 
     /* append Authorization if known in URL, not in header and going direct */
     if (!hdr_out->has(HDR_AUTHORIZATION)) {
         if (!request->flags.proxying && request->login[0] != '\0') {
             httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
                               old_base64_encode(request->login));
         }
     }
 
     /* Fixup (Proxy-)Authorization special cases. Plain relaying dealt with above */
     httpFixupAuthentication(request, hdr_in, hdr_out, flags);
 
@@ -1848,41 +1848,41 @@
             cc->maxAge(getMaxAge(url));
 
         }
 
         /* Enforce sibling relations */
         if (flags.only_if_cached)
             cc->onlyIfCached(true);
 
         hdr_out->putCc(cc);
 
         delete cc;
     }
 
     /* maybe append Connection: keep-alive */
     if (flags.keepalive) {
         hdr_out->putStr(HDR_CONNECTION, "keep-alive");
     }
 
     /* append Front-End-Https */
     if (flags.front_end_https) {
-        if (flags.front_end_https == 1 || request->protocol == AnyP::PROTO_HTTPS)
+        if (flags.front_end_https == 1 || request->url.getScheme() == AnyP::PROTO_HTTPS)
             hdr_out->putStr(HDR_FRONT_END_HTTPS, "On");
     }
 
     if (flags.chunked_request) {
         // Do not just copy the original value so that if the client-side
         // starts decode other encodings, this code may remain valid.
         hdr_out->putStr(HDR_TRANSFER_ENCODING, "chunked");
     }
 
     /* Now mangle the headers. */
     if (Config2.onoff.mangle_request_headers)
         httpHdrMangleList(hdr_out, request, ROR_REQUEST);
 
     if (Config.request_header_add && !Config.request_header_add->empty())
         httpHdrAdd(hdr_out, request, al, *Config.request_header_add);
 
     strConnection.clean();
 }
 
 /**
@@ -1941,41 +1941,41 @@
                 hdr_out->addEntry(e->clone());
             }
         }
 
         break;
 
     case HDR_HOST:
         /** \par Host:
          * Normally Squid rewrites the Host: header.
          * However, there is one case when we don't: If the URL
          * went through our redirector and the admin configured
          * 'redir_rewrites_host' to be off.
          */
         if (request->peer_domain)
             hdr_out->putStr(HDR_HOST, request->peer_domain);
         else if (request->flags.redirected && !Config.onoff.redir_rewrites_host)
             hdr_out->addEntry(e->clone());
         else {
             /* use port# only if not default */
 
-            if (request->port == urlDefaultPort(request->protocol)) {
+            if (request->port == urlDefaultPort(request->url.getScheme())) {
                 hdr_out->putStr(HDR_HOST, request->GetHost());
             } else {
                 httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
                                   request->GetHost(),
                                   (int) request->port);
             }
         }
 
         break;
 
     case HDR_IF_MODIFIED_SINCE:
         /** \par If-Modified-Since:
          * append unless we added our own,
          * but only if cache_miss_revalidate is enabled, or
          *  the request is not cacheable, or
          *  the request contains authentication credentials.
          * \note at most one client's If-Modified-Since header can pass through
          */
         // XXX: need to check and cleanup the auth case so cacheable auth requests get cached.
         if (hdr_out->has(HDR_IF_MODIFIED_SINCE))

=== modified file 'src/internal.cc'
--- src/internal.cc	2013-10-25 00:13:46 +0000
+++ src/internal.cc	2014-04-26 04:02:35 +0000
@@ -56,40 +56,41 @@
     ErrorState *err;
     const char *upath = request->urlpath.termedBuf();
     debugs(76, 3, HERE << clientConn << " requesting '" << upath << "'");
 
     if (0 == strcmp(upath, "/squid-internal-dynamic/netdb")) {
         netdbBinaryExchange(entry);
     } else if (0 == strcmp(upath, "/squid-internal-periodic/store_digest")) {
 #if USE_CACHE_DIGESTS
         const char *msgbuf = "This cache is currently building its digest.\n";
 #else
 
         const char *msgbuf = "This cache does not support Cache Digests.\n";
 #endif
 
         HttpReply *reply = new HttpReply;
         reply->setHeaders(Http::scNotFound, "Not Found", "text/plain", strlen(msgbuf), squid_curtime, -2);
         entry->replaceHttpReply(reply);
         entry->append(msgbuf, strlen(msgbuf));
         entry->complete();
     } else if (0 == strncmp(upath, "/squid-internal-mgr/", 20)) {
+        debugs(17, 2, "calling CacheManager due to URL-path /squid-internal-mgr/");
         CacheManager::GetInstance()->Start(clientConn, request, entry);
     } else {
         debugObj(76, 1, "internalStart: unknown request:\n",
                  request, (ObjPackMethod) & httpRequestPack);
         err = new ErrorState(ERR_INVALID_REQ, Http::scNotFound, request);
         errorAppendEntry(entry, err);
     }
 }
 
 int
 internalCheck(const char *urlpath)
 {
     return (0 == strncmp(urlpath, "/squid-internal-", 16));
 }
 
 int
 internalStaticCheck(const char *urlpath)
 {
     return (0 == strncmp(urlpath, "/squid-internal-static", 22));
 }

=== modified file 'src/peer_select.cc'
--- src/peer_select.cc	2014-04-22 02:47:09 +0000
+++ src/peer_select.cc	2014-04-25 15:28:46 +0000
@@ -674,41 +674,41 @@
     }
     if (p && code != HIER_NONE) {
         debugs(44, 3, "peerSelect: " << hier_code_str[code] << "/" << p->host);
         peerAddFwdServer(&ps->servers, p, code);
     }
 }
 
 /*
  * peerGetSomeDirect
  *
  * Simply adds a 'direct' entry to the FwdServers list if this
  * request can be forwarded directly to the origin server
  */
 static void
 peerGetSomeDirect(ps_state * ps)
 {
     if (ps->direct == DIRECT_NO)
         return;
 
     /* WAIS is not implemented natively */
-    if (ps->request->protocol == AnyP::PROTO_WAIS)
+    if (ps->request->url.getScheme() == AnyP::PROTO_WAIS)
         return;
 
     peerAddFwdServer(&ps->servers, NULL, HIER_DIRECT);
 }
 
 static void
 peerGetSomeParent(ps_state * ps)
 {
     CachePeer *p;
     HttpRequest *request = ps->request;
     hier_code code = HIER_NONE;
     debugs(44, 3, request->method << ' ' << request->GetHost());
 
     if (ps->direct == DIRECT_YES)
         return;
 
     if ((p = peerSourceHashSelectParent(request))) {
         code = SOURCEHASH_PARENT;
 #if USE_AUTH
     } else if ((p = peerUserHashSelectParent(request))) {

=== modified file 'src/tests/testHttpRequest.cc'
--- src/tests/testHttpRequest.cc	2013-10-25 00:13:46 +0000
+++ src/tests/testHttpRequest.cc	2014-04-25 23:37:04 +0000
@@ -26,138 +26,138 @@
     Mem::Init();
     httpHeaderInitModule();
 }
 
 /*
  * Test creating an HttpRequest object from a Url and method
  */
 void
 testHttpRequest::testCreateFromUrlAndMethod()
 {
     /* vanilla url */
     unsigned short expected_port;
     char * url = xstrdup("http://foo:90/bar");
     HttpRequest *aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET);
     expected_port = 90;
     HttpRequest *nullRequest = NULL;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
     CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url));
     xfree(url);
 
     /* vanilla url, different method */
     url = xstrdup("http://foo/bar");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_PUT);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT);
     CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url));
     xfree(url);
 
     /* a connect url with non-CONNECT data */
     url = xstrdup(":foo/bar");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT);
     xfree(url);
     CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest);
 
     /* a CONNECT url with CONNECT data */
     url = xstrdup("foo:45");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT);
     expected_port = 45;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT);
     CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String(""), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url));
     xfree(url);
 }
 
 /*
  * Test creating an HttpRequest object from a Url alone.
  */
 void
 testHttpRequest::testCreateFromUrl()
 {
     /* vanilla url */
     unsigned short expected_port;
     char * url = xstrdup("http://foo:90/bar");
     HttpRequest *aRequest = HttpRequest::CreateFromUrl(url);
     expected_port = 90;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
     CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url));
     xfree(url);
 }
 
 /*
  * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
  */
 void
 testHttpRequest::testIPv6HostColonBug()
 {
     unsigned short expected_port;
     char * url = NULL;
     HttpRequest *aRequest = NULL;
 
     /* valid IPv6 address without port */
     url = xstrdup("http://[2000:800::45]/foo");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
     CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url));
     xfree(url);
 
     /* valid IPv6 address with port */
     url = xstrdup("http://[2000:800::45]:90/foo");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET);
     expected_port = 90;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
     CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url));
     xfree(url);
 
     /* IPv6 address as invalid (bug trigger) */
     url = xstrdup("http://2000:800::45/foo");
     aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET);
     expected_port = 80;
     CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port);
     CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
     CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost()));
     CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath);
-    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol);
+    CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
     CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url));
     xfree(url);
 }
 
 void
 testHttpRequest::testSanityCheckStartLine()
 {
     MemBuf input;
     PrivateHttpRequest engine;
     Http::StatusCode error = Http::scNone;
     size_t hdr_len;
     input.init();
 
     // a valid request line
     input.append("GET / HTTP/1.1\n\n", 16);
     hdr_len = headersEnd(input.content(), input.contentSize());
     CPPUNIT_ASSERT(engine.doSanityCheckStartLine(&input, hdr_len, &error) );
     CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
     input.reset();
     error = Http::scNone;

=== modified file 'src/url.cc'
--- src/url.cc	2014-04-23 15:36:13 +0000
+++ src/url.cc	2014-04-26 05:21:10 +0000
@@ -129,75 +129,70 @@
         return AnyP::PROTO_COAP;
 
     if (strncasecmp(b, "coaps", len) == 0)
         return AnyP::PROTO_COAPS;
 
     if (strncasecmp(b, "gopher", len) == 0)
         return AnyP::PROTO_GOPHER;
 
     if (strncasecmp(b, "wais", len) == 0)
         return AnyP::PROTO_WAIS;
 
     if (strncasecmp(b, "cache_object", len) == 0)
         return AnyP::PROTO_CACHE_OBJECT;
 
     if (strncasecmp(b, "urn", len) == 0)
         return AnyP::PROTO_URN;
 
     if (strncasecmp(b, "whois", len) == 0)
         return AnyP::PROTO_WHOIS;
 
-    if (strncasecmp(b, "internal", len) == 0)
-        return AnyP::PROTO_INTERNAL;
-
     return AnyP::PROTO_NONE;
 }
 
 int
 urlDefaultPort(AnyP::ProtocolType p)
 {
     switch (p) {
 
     case AnyP::PROTO_HTTP:
         return 80;
 
     case AnyP::PROTO_HTTPS:
         return 443;
 
     case AnyP::PROTO_FTP:
         return 21;
 
     case AnyP::PROTO_COAP:
     case AnyP::PROTO_COAPS:
         // coaps:// default is TBA as of draft-ietf-core-coap-08.
         // Assuming IANA policy of allocating same port for base and TLS protocol versions will occur.
         return 5683;
 
     case AnyP::PROTO_GOPHER:
         return 70;
 
     case AnyP::PROTO_WAIS:
         return 210;
 
     case AnyP::PROTO_CACHE_OBJECT:
-
-    case AnyP::PROTO_INTERNAL:
         return CACHE_HTTP_PORT;
 
     case AnyP::PROTO_WHOIS:
         return 43;
 
     default:
         return 0;
     }
 }
 
 /*
  * Parse a URI/URL.
  *
  * If the 'request' arg is non-NULL, put parsed values there instead
  * of allocating a new HttpRequest.
  *
  * This abuses HttpRequest as a way of representing the parsed url
  * and its components.
  * method is used to switch parsers and to init the HttpRequest.
  * If method is Http::METHOD_CONNECT, then rather than a URL a hostname:port is
@@ -486,115 +481,113 @@
 {
     debugs(50, 5, "urnParse: " << urn);
     if (request) {
         request->initHTTP(method, AnyP::PROTO_URN, urn + 4);
         safe_free(request->canonical);
         return request;
     }
 
     return new HttpRequest(method, AnyP::PROTO_URN, urn + 4);
 }
 
 const char *
 urlCanonical(HttpRequest * request)
 {
     LOCAL_ARRAY(char, portbuf, 32);
     LOCAL_ARRAY(char, urlbuf, MAX_URL);
 
     if (request->canonical)
         return request->canonical;
 
-    if (request->protocol == AnyP::PROTO_URN) {
+    if (request->url.getScheme() == AnyP::PROTO_URN) {
         snprintf(urlbuf, MAX_URL, "urn:" SQUIDSTRINGPH,
                  SQUIDSTRINGPRINT(request->urlpath));
     } else {
         switch (request->method.id()) {
 
         case Http::METHOD_CONNECT:
             snprintf(urlbuf, MAX_URL, "%s:%d", request->GetHost(), request->port);
             break;
 
         default:
             {
                 portbuf[0] = '\0';
 
-                if (request->port != urlDefaultPort(request->protocol))
+                if (request->port != urlDefaultPort(request->url.getScheme()))
                     snprintf(portbuf, 32, ":%d", request->port);
 
-                const AnyP::UriScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed.
                 snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s" SQUIDSTRINGPH,
-                         sch.c_str(),
+                         request->url.getScheme().c_str(),
                          request->login,
                          *request->login ? "@" : null_string,
                          request->GetHost(),
                          portbuf,
                          SQUIDSTRINGPRINT(request->urlpath));
             }
         }
     }
 
     return (request->canonical = xstrdup(urlbuf));
 }
 
 /** \todo AYJ: Performance: This is an *almost* duplicate of urlCanonical. But elides the query-string.
  *        After copying it on in the first place! Would be less code to merge the two with a flag parameter.
  *        and never copy the query-string part in the first place
  */
 char *
 urlCanonicalClean(const HttpRequest * request)
 {
     LOCAL_ARRAY(char, buf, MAX_URL);
     LOCAL_ARRAY(char, portbuf, 32);
     LOCAL_ARRAY(char, loginbuf, MAX_LOGIN_SZ + 1);
     char *t;
 
-    if (request->protocol == AnyP::PROTO_URN) {
+    if (request->url.getScheme() == AnyP::PROTO_URN) {
         snprintf(buf, MAX_URL, "urn:" SQUIDSTRINGPH,
                  SQUIDSTRINGPRINT(request->urlpath));
     } else {
         switch (request->method.id()) {
 
         case Http::METHOD_CONNECT:
             snprintf(buf, MAX_URL, "%s:%d", request->GetHost(), request->port);
             break;
 
         default:
             {
                 portbuf[0] = '\0';
 
-                if (request->port != urlDefaultPort(request->protocol))
+                if (request->port != urlDefaultPort(request->url.getScheme()))
                     snprintf(portbuf, 32, ":%d", request->port);
 
                 loginbuf[0] = '\0';
 
                 if ((int) strlen(request->login) > 0) {
                     strcpy(loginbuf, request->login);
 
                     if ((t = strchr(loginbuf, ':')))
                         *t = '\0';
 
                     strcat(loginbuf, "@");
                 }
 
-                const AnyP::UriScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed.
                 snprintf(buf, MAX_URL, "%s://%s%s%s" SQUIDSTRINGPH,
-                         sch.c_str(),
+                         request->url.getScheme().c_str(),
                          loginbuf,
                          request->GetHost(),
                          portbuf,
                          SQUIDSTRINGPRINT(request->urlpath));
 
                 // strip arguments AFTER a question-mark
                 if (Config.onoff.strip_query_terms)
                     if ((t = strchr(buf, '?')))
                         *(++t) = '\0';
             }
         }
     }
 
     if (stringHasCntl(buf))
         xstrncpy(buf, rfc1738_escape_unescaped(buf), MAX_URL);
 
     return buf;
 }
 
 /**
@@ -650,60 +643,59 @@
  *
  * It is assumed that you have already ensured that the URL is relative.
  *
  * If NULL is returned it is an indication that the method in use in the
  * request does not distinguish between relative and absolute and you should
  * use the url unchanged.
  *
  * If non-NULL is returned, it is up to the caller to free the resulting
  * memory using safe_free().
  */
 char *
 urlMakeAbsolute(const HttpRequest * req, const char *relUrl)
 {
 
     if (req->method.id() == Http::METHOD_CONNECT) {
         return (NULL);
     }
 
     char *urlbuf = (char *)xmalloc(MAX_URL * sizeof(char));
 
-    if (req->protocol == AnyP::PROTO_URN) {
+    if (req->url.getScheme() == AnyP::PROTO_URN) {
         snprintf(urlbuf, MAX_URL, "urn:" SQUIDSTRINGPH,
                  SQUIDSTRINGPRINT(req->urlpath));
         return (urlbuf);
     }
 
     size_t urllen;
 
-    const AnyP::UriScheme sch = req->protocol; // temporary, until bug 1961 URL handling is fixed.
-    if (req->port != urlDefaultPort(req->protocol)) {
+    if (req->port != urlDefaultPort(req->url.getScheme())) {
         urllen = snprintf(urlbuf, MAX_URL, "%s://%s%s%s:%d",
-                          sch.c_str(),
+                          req->url.getScheme().c_str(),
                           req->login,
                           *req->login ? "@" : null_string,
                           req->GetHost(),
                           req->port
                          );
     } else {
         urllen = snprintf(urlbuf, MAX_URL, "%s://%s%s%s",
-                          sch.c_str(),
+                          req->url.getScheme().c_str(),
                           req->login,
                           *req->login ? "@" : null_string,
                           req->GetHost()
                          );
     }
 
     if (relUrl[0] == '/') {
         strncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
     } else {
         const char *path = req->urlpath.termedBuf();
         const char *last_slash = strrchr(path, '/');
 
         if (last_slash == NULL) {
             urlbuf[urllen] = '/';
             ++urllen;
             strncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
         } else {
             ++last_slash;
             size_t pathlen = last_slash - path;
             if (pathlen > MAX_URL - urllen - 1) {
@@ -827,41 +819,41 @@
      * they are methods we recieve on our HTTP port,
      * and if we had a FTP listener would not be relevant
      * there.
      *
      * So, we should delegate them to HTTP. The problem is that we
      * do not have a default protocol from the client side of HTTP.
      */
 
     if (r->method == Http::METHOD_CONNECT)
         return 1;
 
     // we support OPTIONS and TRACE directed at us (with a 501 reply, for now)
     // we also support forwarding OPTIONS and TRACE, except for the *-URI ones
     if (r->method == Http::METHOD_OPTIONS || r->method == Http::METHOD_TRACE)
         return (r->header.getInt64(HDR_MAX_FORWARDS) == 0 || r->urlpath != "*");
 
     if (r->method == Http::METHOD_PURGE)
         return 1;
 
     /* does method match the protocol? */
-    switch (r->protocol) {
+    switch (r->url.getScheme()) {
 
     case AnyP::PROTO_URN:
 
     case AnyP::PROTO_HTTP:
 
     case AnyP::PROTO_CACHE_OBJECT:
         rc = 1;
         break;
 
     case AnyP::PROTO_FTP:
 
         if (r->method == Http::METHOD_PUT)
             rc = 1;
 
     case AnyP::PROTO_GOPHER:
 
     case AnyP::PROTO_WAIS:
 
     case AnyP::PROTO_WHOIS:
         if (r->method == Http::METHOD_GET)


