From: Amos Jeffries Date: Wed, 17 Aug 2016 00:38:25 +0000 (+1200) Subject: Better support for unknown URL schemes X-Git-Tag: SQUID_4_0_14~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d31d59d80a8ef8a2b85058fe6504188e43cee5ce;p=thirdparty%2Fsquid.git Better support for unknown URL schemes Squid already contains AnyP::PROTO_UNKNOWN support for unknown protocols but currently does not preserve the actual string value received for them. This adds a textual representation ('image') to the UriScheme object to fill that gap and ensure that all URL representations (ie cache keys, logs and outgoing messages) are generated with the scheme string as it was received rather than implicitly via a registered protocol type. Future work: * add ACL support for arbitrary scheme names * support for comparisons of unknown schemes --- diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 8b926323b0..9ef416d22d 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -44,13 +44,13 @@ HttpRequest::HttpRequest() : init(); } -HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) : +HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath) : HttpMsg(hoRequest) { static unsigned int id = 1; debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id); init(); - initHTTP(aMethod, aProtocol, aUrlpath); + initHTTP(aMethod, aProtocol, aSchemeImg, aUrlpath); } HttpRequest::~HttpRequest() @@ -60,10 +60,10 @@ HttpRequest::~HttpRequest() } void -HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) +HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath) { method = aMethod; - url.setScheme(aProtocol); + url.setScheme(aProtocol, aSchemeImg); url.path(aUrlpath); } @@ -180,11 +180,7 @@ HttpRequest::clone() const copy->pstate = pstate; // TODO: should we assert a specific state here? copy->body_pipe = body_pipe; - copy->url.setScheme(url.getScheme()); - copy->url.userInfo(url.userInfo()); - copy->url.host(url.host()); - copy->url.port(url.port()); - copy->url.path(url.path()); + copy->url = url; // range handled in hdrCacheInit() copy->ims = ims; diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 8d9702ac58..86444ae783 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -49,11 +49,11 @@ public: typedef RefCount Pointer; HttpRequest(); - HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath); + HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath); ~HttpRequest(); virtual void reset(); - void initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath); + void initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath); virtual HttpRequest *clone() const; diff --git a/src/PeerPoolMgr.cc b/src/PeerPoolMgr.cc index 1733e16f70..9fcb4c682a 100644 --- a/src/PeerPoolMgr.cc +++ b/src/PeerPoolMgr.cc @@ -61,7 +61,7 @@ PeerPoolMgr::start() // ErrorState, getOutgoingAddress(), and other APIs may require a request. // We fake one. TODO: Optionally send this request to peers? - request = new HttpRequest(Http::METHOD_OPTIONS, AnyP::PROTO_HTTP, "*"); + request = new HttpRequest(Http::METHOD_OPTIONS, AnyP::PROTO_HTTP, "http", "*"); request->url.host(peer->host); checkpoint("peer initialized"); diff --git a/src/URL.h b/src/URL.h index 7217663e3a..9495a7f62d 100644 --- a/src/URL.h +++ b/src/URL.h @@ -28,6 +28,20 @@ class URL public: URL() : hostIsNumeric_(false), port_(0) {*host_=0;} URL(AnyP::UriScheme const &aScheme); + URL(const URL &other) { + this->operator =(other); + } + URL &operator =(const URL &o) { + scheme_ = o.scheme_; + userInfo_ = o.userInfo_; + memcpy(host_, o.host_, sizeof(host_)); + hostIsNumeric_ = o.hostIsNumeric_; + hostAddr_ = o.hostAddr_; + port_ = o.port_; + path_ = o.path_; + touch(); + return *this; + } void clear() { scheme_=AnyP::PROTO_NONE; @@ -42,7 +56,10 @@ public: AnyP::UriScheme const & getScheme() const {return scheme_;} /// convert the URL scheme to that given - void setScheme(const AnyP::ProtocolType &p) {scheme_=p; touch();} + void setScheme(const AnyP::ProtocolType &p, const char *str) { + scheme_ = AnyP::UriScheme(p, str); + touch(); + } void userInfo(const SBuf &s) {userInfo_=s; touch();} const SBuf &userInfo() const {return userInfo_;} @@ -131,9 +148,17 @@ private: inline std::ostream & operator <<(std::ostream &os, const URL &url) { - if (const char *sc = url.getScheme().c_str()) - os << sc << ":"; - os << "//" << url.authority() << url.path(); + // none means explicit empty string for scheme. + if (url.getScheme() != AnyP::PROTO_NONE) + os << url.getScheme().image(); + os << ":"; + + // no authority section on URN + if (url.getScheme() != AnyP::PROTO_URN) + os << "//" << url.authority(); + + // path is what it is - including absent + os << url.path(); return os; } diff --git a/src/anyp/UriScheme.cc b/src/anyp/UriScheme.cc index a802f615e1..8f1ff4972a 100644 --- a/src/anyp/UriScheme.cc +++ b/src/anyp/UriScheme.cc @@ -11,22 +11,24 @@ #include "squid.h" #include "anyp/UriScheme.h" -char const * -AnyP::UriScheme::c_str() const +AnyP::UriScheme::UriScheme(AnyP::ProtocolType const aScheme, const char *img) : + theScheme_(aScheme) { - if (theScheme_ == AnyP::PROTO_UNKNOWN) - return "(unknown)"; - - static char out[BUFSIZ]; - int p = 0; - - if (theScheme_ > AnyP::PROTO_NONE && theScheme_ < AnyP::PROTO_MAX) { - const char *in = AnyP::ProtocolType_str[theScheme_]; - for (; p < (BUFSIZ-1) && in[p] != '\0'; ++p) - out[p] = xtolower(in[p]); + if (img) + // image could be provided explicitly (case-sensitive) + image_ = img; + + else if (theScheme_ == AnyP::PROTO_UNKNOWN) + // image could be actually unknown and not provided + image_ = "(unknown)"; + + else if (theScheme_ > AnyP::PROTO_NONE && theScheme_ < AnyP::PROTO_MAX) { + // image could be implied by a registered transfer protocol + // which use upper-case labels, so down-case for scheme image + image_ = AnyP::ProtocolType_str[theScheme_]; + image_.toLower(); } - out[p] = '\0'; - return out; + // else, image is an empty string ("://example.com/") } unsigned short diff --git a/src/anyp/UriScheme.h b/src/anyp/UriScheme.h index 4cd03af83d..d20299f293 100644 --- a/src/anyp/UriScheme.h +++ b/src/anyp/UriScheme.h @@ -10,6 +10,7 @@ #define SQUID_ANYP_URISCHEME_H #include "anyp/ProtocolType.h" +#include "sbuf/SBuf.h" #include @@ -23,27 +24,35 @@ class UriScheme { public: UriScheme() : theScheme_(AnyP::PROTO_NONE) {} - UriScheme(AnyP::ProtocolType const aScheme) : theScheme_(aScheme) {} + UriScheme(AnyP::ProtocolType const aScheme, const char *img = nullptr); + UriScheme(const AnyP::UriScheme &o) : theScheme_(o.theScheme_), image_(o.image_) {} + UriScheme(AnyP::UriScheme &&) = default; ~UriScheme() {} - operator AnyP::ProtocolType() const { return theScheme_; } + AnyP::UriScheme& operator=(const AnyP::UriScheme &o) { + theScheme_ = o.theScheme_; + image_ = o.image_; + return *this; + } + AnyP::UriScheme& operator=(AnyP::UriScheme &&) = default; + operator AnyP::ProtocolType() const { return theScheme_; } + // XXX: does not account for comparison of unknown schemes (by image) bool operator != (AnyP::ProtocolType const & aProtocol) const { return theScheme_ != aProtocol; } /** Get a char string representation of the scheme. - * Does not include the ':' or '://" terminators. - * - * An upper bound length of BUFSIZ bytes converted. Remainder will be truncated. - * The result of this call will remain usable only until any subsequest call - * and must be copied if persistence is needed. + * Does not include the ':' or "://" terminators. */ - char const *c_str() const; + SBuf image() const {return image_;} unsigned short defaultPort() const; private: /// This is a typecode pointer into the enum/registry of protocols handled. AnyP::ProtocolType theScheme_; + + /// the string representation + SBuf image_; }; } // namespace AnyP @@ -51,7 +60,7 @@ private: inline std::ostream & operator << (std::ostream &os, AnyP::UriScheme const &scheme) { - os << scheme.c_str(); + os << scheme.image(); return os; } diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 2a860be869..3a6a76a95e 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -3381,7 +3381,7 @@ parsePortSpecification(const AnyP::PortCfgPointer &s, char *token) s->name = xstrdup(token); s->connection_auth_disabled = false; - const char *portType = AnyP::UriScheme(s->transport.protocol).c_str(); + const SBuf &portType = AnyP::UriScheme(s->transport.protocol).image(); if (*token == '[') { /* [ipv6]:port */ @@ -3780,7 +3780,7 @@ parsePortCfg(AnyP::PortCfgPointer *head, const char *optionName) // clone the port options from *s to *(s->next) s->next = s->clone(); s->next->s.setIPv4(); - debugs(3, 3, AnyP::UriScheme(s->transport.protocol).c_str() << "_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s); + debugs(3, 3, AnyP::UriScheme(s->transport.protocol).image() << "_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s); } while (*head != NULL) @@ -3824,7 +3824,7 @@ dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s) // TODO: compare against prefix of 'n' instead of assuming http_port if (s->transport.protocol != AnyP::PROTO_HTTP) - storeAppendPrintf(e, " protocol=%s", AnyP::UriScheme(s->transport.protocol).c_str()); + storeAppendPrintf(e, " protocol=%s", AnyP::ProtocolType_str[s->transport.protocol]); if (s->allow_direct) storeAppendPrintf(e, " allow-direct"); diff --git a/src/carp.cc b/src/carp.cc index 0c463e5659..cbb97e5a57 100644 --- a/src/carp.cc +++ b/src/carp.cc @@ -167,7 +167,7 @@ carpSelectParent(HttpRequest * request) // this code follows URI syntax pattern. // corner cases should use the full effective request URI if (tp->options.carp_key.scheme) { - key.append(request->url.getScheme().c_str()); + key.append(request->url.getScheme().image()); if (key.length()) //if the scheme is not empty key.append("://"); } diff --git a/src/client_side.cc b/src/client_side.cc index 1ed432c2dc..a84b0589dd 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1221,7 +1221,8 @@ prepareAcceleratedURL(ConnStateData * conn, ClientHttpRequest *http, const Http1 } // else nothing to alter port-wise. const int url_sz = hp->requestUri().length() + 32 + Config.appendDomainLen + strlen(host); http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s" SQUIDSBUFPH, AnyP::UriScheme(conn->transferProtocol.protocol).c_str(), host, SQUIDSBUFPRINT(url)); + const SBuf &scheme = AnyP::UriScheme(conn->transferProtocol.protocol).image(); + snprintf(http->uri, url_sz, SQUIDSBUFPH "://%s" SQUIDSBUFPH, SQUIDSBUFPRINT(scheme), host, SQUIDSBUFPRINT(url)); debugs(33, 5, "ACCEL VHOST REWRITE: " << http->uri); } else if (conn->port->defaultsite /* && !vhost */) { debugs(33, 5, "ACCEL DEFAULTSITE REWRITE: defaultsite=" << conn->port->defaultsite << " + vport=" << vport); @@ -1233,8 +1234,9 @@ prepareAcceleratedURL(ConnStateData * conn, ClientHttpRequest *http, const Http1 if (vport > 0) { snprintf(vportStr, sizeof(vportStr),":%d",vport); } - snprintf(http->uri, url_sz, "%s://%s%s" SQUIDSBUFPH, - AnyP::UriScheme(conn->transferProtocol.protocol).c_str(), conn->port->defaultsite, vportStr, SQUIDSBUFPRINT(url)); + const SBuf &scheme = AnyP::UriScheme(conn->transferProtocol.protocol).image(); + snprintf(http->uri, url_sz, SQUIDSBUFPH "://%s%s" SQUIDSBUFPH, + SQUIDSBUFPRINT(scheme), conn->port->defaultsite, vportStr, SQUIDSBUFPRINT(url)); debugs(33, 5, "ACCEL DEFAULTSITE REWRITE: " << http->uri); } else if (vport > 0 /* && (!vhost || no Host:) */) { debugs(33, 5, "ACCEL VPORT REWRITE: *_port IP + vport=" << vport); @@ -1242,9 +1244,9 @@ prepareAcceleratedURL(ConnStateData * conn, ClientHttpRequest *http, const Http1 const int url_sz = hp->requestUri().length() + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN); - snprintf(http->uri, url_sz, "%s://%s:%d" SQUIDSBUFPH, - AnyP::UriScheme(conn->transferProtocol.protocol).c_str(), - ipbuf, vport, SQUIDSBUFPRINT(url)); + const SBuf &scheme = AnyP::UriScheme(conn->transferProtocol.protocol).image(); + snprintf(http->uri, url_sz, SQUIDSBUFPH "://%s:%d" SQUIDSBUFPH, + SQUIDSBUFPRINT(scheme), ipbuf, vport, SQUIDSBUFPRINT(url)); debugs(33, 5, "ACCEL VPORT REWRITE: " << http->uri); } } @@ -1262,8 +1264,9 @@ prepareTransparentURL(ConnStateData * conn, ClientHttpRequest *http, const Http1 const int url_sz = hp->requestUri().length() + 32 + Config.appendDomainLen + strlen(host); http->uri = (char *)xcalloc(url_sz, 1); - snprintf(http->uri, url_sz, "%s://%s" SQUIDSBUFPH, - AnyP::UriScheme(conn->transferProtocol.protocol).c_str(), host, SQUIDSBUFPRINT(hp->requestUri())); + const SBuf &scheme = AnyP::UriScheme(conn->transferProtocol.protocol).image(); + snprintf(http->uri, url_sz, SQUIDSBUFPH "://%s" SQUIDSBUFPH, + SQUIDSBUFPRINT(scheme), host, SQUIDSBUFPRINT(hp->requestUri())); debugs(33, 5, "TRANSPARENT HOST REWRITE: " << http->uri); } else { /* Put the local socket IP address as the hostname. */ @@ -1271,8 +1274,9 @@ prepareTransparentURL(ConnStateData * conn, ClientHttpRequest *http, const Http1 http->uri = (char *)xcalloc(url_sz, 1); static char ipbuf[MAX_IPSTRLEN]; http->getConn()->clientConnection->local.toHostStr(ipbuf,MAX_IPSTRLEN); - snprintf(http->uri, url_sz, "%s://%s:%d" SQUIDSBUFPH, - AnyP::UriScheme(http->getConn()->transferProtocol.protocol).c_str(), + const SBuf &scheme = AnyP::UriScheme(http->getConn()->transferProtocol.protocol).image(); + snprintf(http->uri, url_sz, SQUIDSBUFPH "://%s:%d" SQUIDSBUFPH, + SQUIDSBUFPRINT(scheme), ipbuf, http->getConn()->clientConnection->local.port(), SQUIDSBUFPRINT(hp->requestUri())); debugs(33, 5, "TRANSPARENT REWRITE: " << http->uri); } @@ -1679,7 +1683,7 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, http->flags.internal = true; } else if (Config.onoff.global_internal_static && internalStaticCheck(request->url.path())) { debugs(33, 2, "internal URL found: " << request->url.getScheme() << "://" << request->url.authority(true) << " (global_internal_static on)"); - request->url.setScheme(AnyP::PROTO_HTTP); + request->url.setScheme(AnyP::PROTO_HTTP, "http"); request->url.host(internalHostname()); request->url.port(getMyPort()); http->flags.internal = true; @@ -3445,7 +3449,7 @@ static void clientHttpConnectionsOpen(void) { for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) { - const char *scheme = AnyP::UriScheme(s->transport.protocol).c_str(); + const SBuf &scheme = AnyP::UriScheme(s->transport.protocol).image(); if (MAXTCPLISTENPORTS == NHttpSockets) { debugs(1, DBG_IMPORTANT, "WARNING: You have too many '" << scheme << "_port' lines."); diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index b89bf8e9b4..b5fbd88fa9 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -2259,7 +2259,7 @@ clientReplyContext::createStoreEntry(const HttpRequestMethod& m, RequestFlags re */ if (http->request == NULL) { - http->request = new HttpRequest(m, AnyP::PROTO_NONE, null_string); + http->request = new HttpRequest(m, AnyP::PROTO_NONE, "http", null_string); HTTPMSGLOCK(http->request); } diff --git a/src/errorpage.cc b/src/errorpage.cc index 200af2a30e..3c06357fb5 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -946,7 +946,8 @@ ErrorState::Convert(char token, bool building_deny_info_url, bool allowRecursion case 'P': if (request) { - p = request->url.getScheme().c_str(); + const SBuf &m = request->url.getScheme().image(); + mb.append(m.rawContent(), m.length()); } else if (!building_deny_info_url) { p = "[unknown protocol]"; } diff --git a/src/format/Format.cc b/src/format/Format.cc index 7ca4f53036..0f4139d700 100644 --- a/src/format/Format.cc +++ b/src/format/Format.cc @@ -996,7 +996,9 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS case LFT_CLIENT_REQ_URLSCHEME: if (al->request) { - out = al->request->url.getScheme().c_str(); + const SBuf s(al->request->url.getScheme().image()); + sb.append(s.rawContent(), s.length()); + out = sb.termedBuf(); quote = 1; } break; @@ -1075,7 +1077,9 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS case LFT_SERVER_REQ_URLSCHEME: if (al->adapted_request) { - out = al->adapted_request->url.getScheme().c_str(); + const SBuf s(al->adapted_request->url.getScheme().image()); + sb.append(s.rawContent(), s.length()); + out = sb.termedBuf(); quote = 1; } break; diff --git a/src/tests/stub_HttpRequest.cc b/src/tests/stub_HttpRequest.cc index eddd426102..69bedc5995 100644 --- a/src/tests/stub_HttpRequest.cc +++ b/src/tests/stub_HttpRequest.cc @@ -16,10 +16,10 @@ // void httpRequestPack(void *obj, Packable *p); HttpRequest::HttpRequest() : HttpMsg(hoRequest) {STUB} -HttpRequest::HttpRequest(const HttpRequestMethod &, AnyP::ProtocolType, const char *) : HttpMsg(hoRequest) {STUB} +HttpRequest::HttpRequest(const HttpRequestMethod &, AnyP::ProtocolType, const char *, const char *) : HttpMsg(hoRequest) {STUB} HttpRequest::~HttpRequest() STUB void HttpRequest::reset() STUB -void HttpRequest::initHTTP(const HttpRequestMethod &, AnyP::ProtocolType, const char *) STUB +void HttpRequest::initHTTP(const HttpRequestMethod &, AnyP::ProtocolType, const char *, const char *) STUB HttpRequest * HttpRequest::clone() const STUB_RETVAL(NULL) bool HttpRequest::maybeCacheable() STUB_RETVAL(false) bool HttpRequest::conditional() const STUB_RETVAL(false) diff --git a/src/tests/testUriScheme.cc b/src/tests/testUriScheme.cc index 3cc018e7dd..1b790b1a0e 100644 --- a/src/tests/testUriScheme.cc +++ b/src/tests/testUriScheme.cc @@ -112,9 +112,9 @@ testUriScheme::testConstructprotocol_t() void testUriScheme::testC_str() { - String lhs("wais"); + SBuf lhs("wais"); AnyP::UriScheme wais(AnyP::PROTO_WAIS); - String rhs(wais.c_str()); + SBuf rhs(wais.image()); CPPUNIT_ASSERT_EQUAL(lhs, rhs); } diff --git a/src/url.cc b/src/url.cc index 55f20d88f8..8cfe220eb9 100644 --- a/src/url.cc +++ b/src/url.cc @@ -18,6 +18,7 @@ static HttpRequest *urlParseFinish(const HttpRequestMethod& method, const AnyP::ProtocolType protocol, + const char *const protoStr, const char *const urlpath, const char *const host, const SBuf &login, @@ -157,6 +158,9 @@ urlParseProtocol(const char *b) if (strncasecmp(b, "whois", len) == 0) return AnyP::PROTO_WHOIS; + if (len > 0) + return AnyP::PROTO_UNKNOWN; + return AnyP::PROTO_NONE; } @@ -214,8 +218,8 @@ urlParse(const HttpRequestMethod& method, char *url, HttpRequest *request) } else if ((method == Http::METHOD_OPTIONS || method == Http::METHOD_TRACE) && URL::Asterisk().cmp(url) == 0) { protocol = AnyP::PROTO_HTTP; - port = AnyP::UriScheme(protocol).defaultPort(); - return urlParseFinish(method, protocol, url, host, SBuf(), port, request); + port = 80; // or the slow way ... AnyP::UriScheme(protocol,"http").defaultPort(); + return urlParseFinish(method, protocol, "http", url, host, SBuf(), port, request); } else if (!strncmp(url, "urn:", 4)) { return urnParse(method, url, request); } else { @@ -422,7 +426,7 @@ urlParse(const HttpRequestMethod& method, char *url, HttpRequest *request) } } - return urlParseFinish(method, protocol, urlpath, host, SBuf(login), port, request); + return urlParseFinish(method, protocol, proto, urlpath, host, SBuf(login), port, request); } /** @@ -433,6 +437,7 @@ urlParse(const HttpRequestMethod& method, char *url, HttpRequest *request) static HttpRequest * urlParseFinish(const HttpRequestMethod& method, const AnyP::ProtocolType protocol, + const char *const protoStr, // for unknown protocols const char *const urlpath, const char *const host, const SBuf &login, @@ -440,9 +445,9 @@ urlParseFinish(const HttpRequestMethod& method, HttpRequest *request) { if (NULL == request) - request = new HttpRequest(method, protocol, urlpath); + request = new HttpRequest(method, protocol, protoStr, urlpath); else { - request->initHTTP(method, protocol, urlpath); + request->initHTTP(method, protocol, protoStr, urlpath); } request->url.host(host); @@ -456,11 +461,11 @@ urnParse(const HttpRequestMethod& method, char *urn, HttpRequest *request) { debugs(50, 5, "urnParse: " << urn); if (request) { - request->initHTTP(method, AnyP::PROTO_URN, urn + 4); + request->initHTTP(method, AnyP::PROTO_URN, "urn", urn + 4); return request; } - return new HttpRequest(method, AnyP::PROTO_URN, urn + 4); + return new HttpRequest(method, AnyP::PROTO_URN, "urn", urn + 4); } void @@ -496,7 +501,8 @@ URL::absolute() const // TODO: most URL will be much shorter, avoid allocating this much absolute_.reserveCapacity(MAX_URL); - absolute_.appendf("%s:", getScheme().c_str()); + absolute_.append(getScheme().image()); + absolute_.append(":",1); if (getScheme() != AnyP::PROTO_URN) { absolute_.append("//", 2); const bool omitUserInfo = getScheme() == AnyP::PROTO_HTTP || @@ -620,8 +626,9 @@ urlMakeAbsolute(const HttpRequest * req, const char *relUrl) } SBuf authorityForm = req->url.authority(); // host[:port] - size_t urllen = snprintf(urlbuf, MAX_URL, "%s://" SQUIDSBUFPH "%s" SQUIDSBUFPH, - req->url.getScheme().c_str(), + const SBuf &scheme = req->url.getScheme().image(); + size_t urllen = snprintf(urlbuf, MAX_URL, SQUIDSBUFPH "://" SQUIDSBUFPH "%s" SQUIDSBUFPH, + SQUIDSBUFPRINT(scheme), SQUIDSBUFPRINT(req->url.userInfo()), !req->url.userInfo().isEmpty() ? "@" : "", SQUIDSBUFPRINT(authorityForm));