298 строки
12 KiB
C
298 строки
12 KiB
C
|
/***
|
||
|
* Copyright (C) Microsoft. All rights reserved.
|
||
|
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
||
|
*
|
||
|
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||
|
*
|
||
|
* Builder style class for creating URIs.
|
||
|
*
|
||
|
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
||
|
*
|
||
|
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||
|
****/
|
||
|
|
||
|
// Copied and modified slightly from https://github.com/microsoft/cpprestsdk/blob/fd6aa00c18a7fb8dbe957175078f02346775045a/Release/include/cpprest/uri_builder.h
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "base_uri.h"
|
||
|
#include <string>
|
||
|
|
||
|
namespace signalr
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Builder for constructing URIs incrementally.
|
||
|
/// </summary>
|
||
|
class uri_builder
|
||
|
{
|
||
|
public:
|
||
|
/// <summary>
|
||
|
/// Creates a builder with an initially empty URI.
|
||
|
/// </summary>
|
||
|
uri_builder() = default;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Creates a builder with a existing URI object.
|
||
|
/// </summary>
|
||
|
/// <param name="uri_str">Encoded string containing the URI.</param>
|
||
|
uri_builder(const uri& uri_str) : m_uri(uri_str.m_components) {}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the scheme component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI scheme as a string.</returns>
|
||
|
const std::string& scheme() const { return m_uri.m_scheme; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the user information component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI user information as a string.</returns>
|
||
|
const std::string& user_info() const { return m_uri.m_user_info; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the host component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI host as a string.</returns>
|
||
|
const std::string& host() const { return m_uri.m_host; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the port component of the URI. Returns -1 if no port is specified.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI port as an integer.</returns>
|
||
|
int port() const { return m_uri.m_port; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the path component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI path as a string.</returns>
|
||
|
const std::string& path() const { return m_uri.m_path; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the query component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI query as a string.</returns>
|
||
|
const std::string& query() const { return m_uri.m_query; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get the fragment component of the URI as an encoded string.
|
||
|
/// </summary>
|
||
|
/// <returns>The URI fragment as a string.</returns>
|
||
|
const std::string& fragment() const { return m_uri.m_fragment; }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the scheme of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="scheme">Uri scheme.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_scheme(const std::string& scheme)
|
||
|
{
|
||
|
m_uri.m_scheme = scheme;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the user info component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="user_info">User info as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_user_info(const std::string& user_info, bool do_encoding = false)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
{
|
||
|
m_uri.m_user_info = uri::encode_uri(user_info, uri::components::user_info);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_uri.m_user_info = user_info;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the host component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="host">Host as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_host(const std::string& host, bool do_encoding = false)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
{
|
||
|
m_uri.m_host = uri::encode_uri(host, uri::components::host);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_uri.m_host = host;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the port component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="port">Port as an integer.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_port(int port)
|
||
|
{
|
||
|
m_uri.m_port = port;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the port component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="port">Port as a string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
/// <remarks>When string can't be converted to an integer the port is left unchanged.</remarks>
|
||
|
uri_builder& set_port(const std::string& port);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the path component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="path">Path as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_path(const std::string& path, bool do_encoding = false)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
{
|
||
|
m_uri.m_path = uri::encode_uri(path, uri::components::path);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_uri.m_path = path;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the query component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="query">Query as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_query(const std::string& query, bool do_encoding = false)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
{
|
||
|
m_uri.m_query = uri::encode_uri(query, uri::components::query);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_uri.m_query = query;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Set the fragment component of the URI.
|
||
|
/// </summary>
|
||
|
/// <param name="fragment">Fragment as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this <c>uri_builder</c> to support chaining.</returns>
|
||
|
uri_builder& set_fragment(const std::string& fragment, bool do_encoding = false)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
{
|
||
|
m_uri.m_fragment = uri::encode_uri(fragment, uri::components::fragment);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_uri.m_fragment = fragment;
|
||
|
}
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Clears all components of the underlying URI in this uri_builder.
|
||
|
/// </summary>
|
||
|
void clear() { m_uri = details::uri_components(); }
|
||
|
|
||
|
/// <summary>
|
||
|
/// Appends another path to the path of this uri_builder.
|
||
|
/// </summary>
|
||
|
/// <param name="path">Path to append as a already encoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||
|
uri_builder& append_path(const std::string& path, bool do_encoding = false);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Appends the raw contents of the path argument to the path of this uri_builder with no separator de-duplication.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// The path argument is appended after adding a '/' separator without regards to the contents of path. If an empty
|
||
|
/// string is provided, this function will immediately return without changes to the stored path value. For example:
|
||
|
/// if the current contents are "/abc" and path="/xyz", the result will be "/abc//xyz".
|
||
|
/// </remarks>
|
||
|
/// <param name="path">Path to append as a already encoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||
|
uri_builder& append_path_raw(const std::string& path, bool do_encoding = false);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Appends another query to the query of this uri_builder.
|
||
|
/// </summary>
|
||
|
/// <param name="query">Query to append as a decoded string.</param>
|
||
|
/// <param name="do_encoding">Specify whether to apply URI encoding to the given string.</param>
|
||
|
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||
|
uri_builder& append_query(const std::string& query, bool do_encoding = false);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Appends an relative uri (Path, Query and fragment) at the end of the current uri.
|
||
|
/// </summary>
|
||
|
/// <param name="relative_uri">The relative uri to append.</param>
|
||
|
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||
|
uri_builder& append(const uri& relative_uri);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Appends another query to the query of this uri_builder, encoding it first. This overload is useful when building
|
||
|
/// a query segment of the form "element=10", where the right hand side of the query is stored as a type other than
|
||
|
/// a string, for instance, an integral type.
|
||
|
/// </summary>
|
||
|
/// <param name="name">The name portion of the query string</param>
|
||
|
/// <param name="value">The value portion of the query string</param>
|
||
|
/// <returns>A reference to this uri_builder to support chaining.</returns>
|
||
|
template<typename T>
|
||
|
uri_builder& append_query(const std::string& name, const T& value, bool do_encoding = true)
|
||
|
{
|
||
|
if (do_encoding)
|
||
|
append_query_encode_impl(name, value);
|
||
|
else
|
||
|
append_query_no_encode_impl(name, value);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Combine and validate the URI components into a encoded string. An exception will be thrown if the URI is
|
||
|
/// invalid.
|
||
|
/// </summary>
|
||
|
/// <returns>The created URI as a string.</returns>
|
||
|
std::string to_string() const;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Combine and validate the URI components into a URI class instance. An exception will be thrown if the URI is
|
||
|
/// invalid.
|
||
|
/// </summary>
|
||
|
/// <returns>The create URI as a URI class instance.</returns>
|
||
|
uri to_uri() const;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Validate the generated URI from all existing components of this uri_builder.
|
||
|
/// </summary>
|
||
|
/// <returns>Whether the URI is valid.</returns>
|
||
|
bool is_valid();
|
||
|
|
||
|
private:
|
||
|
void append_query_encode_impl(const std::string& name, const std::string& value);
|
||
|
void append_query_no_encode_impl(const std::string& name, const std::string& value);
|
||
|
|
||
|
details::uri_components m_uri;
|
||
|
};
|
||
|
} // namespace signalr
|