Fix URL compositing in Beast (RIPD-636).

This commit is contained in:
Nik Bougalis
2014-10-13 18:42:22 -07:00
committed by Tom Ritchford
parent 75c8d7aa57
commit 9d33e4bd7b
8 changed files with 273 additions and 357 deletions

View File

@@ -21,146 +21,209 @@
namespace beast {
URL::URL ()
: m_port (0)
{
}
URL::URL (
String scheme_,
String host_,
std::string scheme_,
std::string host_,
std::uint16_t port_,
String port_string_,
String path_,
String query_,
String fragment_,
String userinfo_)
: m_scheme (scheme_)
, m_host (host_)
, m_port (port_)
, m_port_string (port_string_)
, m_path (path_)
, m_query (query_)
, m_fragment (fragment_)
, m_userinfo (userinfo_)
std::string port_string_,
std::string path_,
std::string query_,
std::string fragment_,
std::string userinfo_)
: m_scheme (scheme_)
, m_host (host_)
, m_port (port_)
, m_port_string (port_string_)
, m_path (path_)
, m_query (query_)
, m_fragment (fragment_)
, m_userinfo (userinfo_)
{
}
URL::URL (URL const& other)
: m_scheme (other.m_scheme)
, m_host (other.m_host)
, m_port (other.m_port)
, m_port_string (other.m_port_string)
, m_path (other.m_path)
, m_query (other.m_query)
, m_fragment (other.m_fragment)
, m_userinfo (other.m_userinfo)
{
}
URL& URL::operator= (URL const& other)
{
m_scheme = other.m_scheme;
m_host = other.m_host;
m_port = other.m_port;
m_port_string = other.m_port_string;
m_path = other.m_path;
m_query = other.m_query;
m_fragment = other.m_fragment;
m_userinfo = other.m_userinfo;
return *this;
}
//------------------------------------------------------------------------------
bool URL::empty () const
bool
URL::empty () const
{
return m_scheme == String::empty;
return m_scheme.empty ();
}
String URL::scheme () const
std::string
const& URL::scheme () const
{
return m_scheme;
}
String URL::host () const
std::string
const& URL::host () const
{
return m_host;
}
String URL::port_string () const
std::string
const& URL::port_string () const
{
return m_port_string;
}
std::uint16_t URL::port () const
std::uint16_t
URL::port () const
{
return m_port;
}
String URL::path () const
std::string
const& URL::path () const
{
return m_path;
}
String URL::query () const
std::string
const& URL::query () const
{
return m_query;
}
String URL::fragment () const
std::string
const& URL::fragment () const
{
return m_fragment;
}
String URL::userinfo () const
std::string
const& URL::userinfo () const
{
return m_userinfo;
}
//------------------------------------------------------------------------------
/*
From
http://en.wikipedia.org/wiki/URI_scheme
<scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]
e.g.
foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose
*/
String URL::toString () const
std::pair<bool, URL>
parse_URL(std::string const& url)
{
String s;
std::size_t const buflen (url.size ());
char const* const buf (url.c_str ());
s = scheme () + "://";
if (userinfo () != String::empty)
s = userinfo () + "@";
joyent::http_parser_url parser;
s = s + host ();
if (joyent::http_parser_parse_url (buf, buflen, false, &parser) != 0)
return std::make_pair (false, URL{});
if (port () != 0)
s = s + ":" + String::fromNumber (port ());
std::string scheme;
std::string host;
std::uint16_t port (0);
std::string port_string;
std::string path;
std::string query;
std::string fragment;
std::string userinfo;
s = s + path ();
if ((parser.field_set & (1<<joyent::UF_SCHEMA)) != 0)
{
scheme = std::string (
buf + parser.field_data [joyent::UF_SCHEMA].off,
parser.field_data [joyent::UF_SCHEMA].len);
}
if (query () != String::empty)
s = "?" + query ();
if ((parser.field_set & (1<<joyent::UF_HOST)) != 0)
{
host = std::string (
buf + parser.field_data [joyent::UF_HOST].off,
parser.field_data [joyent::UF_HOST].len);
}
if (fragment () != String::empty)
s = "#" + fragment ();
if ((parser.field_set & (1<<joyent::UF_PORT)) != 0)
{
port = parser.port;
port_string = std::string (
buf + parser.field_data [joyent::UF_PORT].off,
parser.field_data [joyent::UF_PORT].len);
}
if ((parser.field_set & (1<<joyent::UF_PATH)) != 0)
{
path = std::string (
buf + parser.field_data [joyent::UF_PATH].off,
parser.field_data [joyent::UF_PATH].len);
}
if ((parser.field_set & (1<<joyent::UF_QUERY)) != 0)
{
query = std::string (
buf + parser.field_data [joyent::UF_QUERY].off,
parser.field_data [joyent::UF_QUERY].len);
}
if ((parser.field_set & (1<<joyent::UF_FRAGMENT)) != 0)
{
fragment = std::string (
buf + parser.field_data [joyent::UF_FRAGMENT].off,
parser.field_data [joyent::UF_FRAGMENT].len);
}
if ((parser.field_set & (1<<joyent::UF_USERINFO)) != 0)
{
userinfo = std::string (
buf + parser.field_data [joyent::UF_USERINFO].off,
parser.field_data [joyent::UF_USERINFO].len);
}
return std::make_pair (true,
URL {scheme, host, port, port_string, path, query, fragment, userinfo});
}
std::string
to_string (URL const& url)
{
std::string s;
if (!url.empty ())
{
// Pre-allocate enough for components and inter-component separators
s.reserve (
url.scheme ().length () + url.userinfo ().length () +
url.host ().length () + url.port_string ().length () +
url.query ().length () + url.fragment ().length () + 16);
s.append (url.scheme ());
s.append ("://");
if (!url.userinfo ().empty ())
{
s.append (url.userinfo ());
s.append ("@");
}
s.append (url.host ());
if (url.port ())
{
s.append (":");
s.append (url.port_string ());
}
s.append (url.path ());
if (!url.query ().empty ())
{
s.append ("?");
s.append (url.query ());
}
if (!url.fragment ().empty ())
{
s.append ("#");
s.append (url.fragment ());
}
}
return s;
}
std::string URL::to_string() const
std::ostream&
operator<< (std::ostream &os, URL const& url)
{
return toString().toStdString();
}
std::ostream& operator<< (std::ostream &os, URL const& url)
{
os << url.to_string();
os << to_string (url);
return os;
}