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()
}
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);
}
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;
typedef RefCount<HttpRequest> 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;
// 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");
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;
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_;}
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;
}
#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
#define SQUID_ANYP_URISCHEME_H
#include "anyp/ProtocolType.h"
+#include "sbuf/SBuf.h"
#include <iosfwd>
{
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
inline std::ostream &
operator << (std::ostream &os, AnyP::UriScheme const &scheme)
{
- os << scheme.c_str();
+ os << scheme.image();
return os;
}
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 */
// 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)
// 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");
// 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("://");
}
} // 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);
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);
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);
}
}
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. */
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);
}
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;
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.");
*/
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);
}
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]";
}
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;
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;
// 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)
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);
}
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,
if (strncasecmp(b, "whois", len) == 0)
return AnyP::PROTO_WHOIS;
+ if (len > 0)
+ return AnyP::PROTO_UNKNOWN;
+
return AnyP::PROTO_NONE;
}
} 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 {
}
}
- return urlParseFinish(method, protocol, urlpath, host, SBuf(login), port, request);
+ return urlParseFinish(method, protocol, proto, urlpath, host, SBuf(login), port, 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,
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);
{
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
// 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 ||
}
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));