mirror of
https://github.com/tribufu/sdk-cpp
synced 2025-06-17 04:54:19 +00:00
323 lines
11 KiB
C++
Vendored
323 lines
11 KiB
C++
Vendored
/***
|
|
* Copyright (C) Microsoft. All rights reserved.
|
|
* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
|
|
*
|
|
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
*
|
|
* For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk
|
|
*
|
|
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
****/
|
|
#pragma once
|
|
|
|
#include "cpprest/asyncrt_utils.h"
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <system_error>
|
|
#include <vector>
|
|
|
|
namespace web
|
|
{
|
|
namespace http
|
|
{
|
|
/// <summary>
|
|
/// Binds an individual reference to a string value.
|
|
/// </summary>
|
|
/// <typeparam name="key_type">The type of string value.</typeparam>
|
|
/// <typeparam name="_t">The type of the value to bind to.</typeparam>
|
|
/// <param name="text">The string value.</param>
|
|
/// <param name="ref">The value to bind to.</param>
|
|
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
|
template<typename key_type, typename _t>
|
|
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release, std::istringstream instead.")
|
|
bool bind(const key_type& text, _t& ref) // const
|
|
{
|
|
utility::istringstream_t iss(text);
|
|
iss >> ref;
|
|
if (iss.fail() || !iss.eof())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Binds an individual reference to a string value.
|
|
/// This specialization is need because <c>istringstream::>></c> delimits on whitespace.
|
|
/// </summary>
|
|
/// <typeparam name="key_type">The type of the string value.</typeparam>
|
|
/// <param name="text">The string value.</param>
|
|
/// <param name="ref">The value to bind to.</param>
|
|
/// <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
|
|
template<typename key_type>
|
|
CASABLANCA_DEPRECATED("This API is deprecated and will be removed in a future release.")
|
|
bool bind(const key_type& text, utility::string_t& ref) // const
|
|
{
|
|
ref = text;
|
|
return true;
|
|
}
|
|
|
|
namespace details
|
|
{
|
|
template<typename key_type, typename _t>
|
|
bool bind_impl(const key_type& text, _t& ref)
|
|
{
|
|
utility::istringstream_t iss(text);
|
|
iss.imbue(std::locale::classic());
|
|
iss >> ref;
|
|
if (iss.fail() || !iss.eof())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
template<typename key_type>
|
|
bool bind_impl(const key_type& text, utf16string& ref)
|
|
{
|
|
ref = utility::conversions::to_utf16string(text);
|
|
return true;
|
|
}
|
|
|
|
template<typename key_type>
|
|
bool bind_impl(const key_type& text, std::string& ref)
|
|
{
|
|
ref = utility::conversions::to_utf8string(text);
|
|
return true;
|
|
}
|
|
} // namespace details
|
|
|
|
/// <summary>
|
|
/// Represents HTTP headers, acts like a map.
|
|
/// </summary>
|
|
class http_headers
|
|
{
|
|
public:
|
|
/// Function object to perform case insensitive comparison of wstrings.
|
|
struct _case_insensitive_cmp
|
|
{
|
|
bool operator()(const utility::string_t& str1, const utility::string_t& str2) const
|
|
{
|
|
return utility::details::str_iless(str1, str2);
|
|
}
|
|
};
|
|
|
|
private:
|
|
typedef std::map<utility::string_t, utility::string_t, _case_insensitive_cmp> inner_container;
|
|
|
|
public:
|
|
/// <summary>
|
|
/// STL-style typedefs
|
|
/// </summary>
|
|
typedef inner_container::key_type key_type;
|
|
typedef inner_container::key_compare key_compare;
|
|
typedef inner_container::allocator_type allocator_type;
|
|
typedef inner_container::size_type size_type;
|
|
typedef inner_container::difference_type difference_type;
|
|
typedef inner_container::pointer pointer;
|
|
typedef inner_container::const_pointer const_pointer;
|
|
typedef inner_container::reference reference;
|
|
typedef inner_container::const_reference const_reference;
|
|
typedef inner_container::iterator iterator;
|
|
typedef inner_container::const_iterator const_iterator;
|
|
typedef inner_container::reverse_iterator reverse_iterator;
|
|
typedef inner_container::const_reverse_iterator const_reverse_iterator;
|
|
|
|
/// <summary>
|
|
/// Constructs an empty set of HTTP headers.
|
|
/// </summary>
|
|
http_headers() {}
|
|
|
|
/// <summary>
|
|
/// Copy constructor.
|
|
/// </summary>
|
|
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
|
http_headers(const http_headers& other) : m_headers(other.m_headers) {}
|
|
|
|
/// <summary>
|
|
/// Assignment operator.
|
|
/// </summary>
|
|
/// <param name="other">An <c>http_headers</c> object to copy from.</param>
|
|
http_headers& operator=(const http_headers& other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
m_headers = other.m_headers;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Move constructor.
|
|
/// </summary>
|
|
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
|
http_headers(http_headers&& other) : m_headers(std::move(other.m_headers)) {}
|
|
|
|
/// <summary>
|
|
/// Move assignment operator.
|
|
/// </summary>
|
|
/// <param name="other">An <c>http_headers</c> object to move.</param>
|
|
http_headers& operator=(http_headers&& other)
|
|
{
|
|
if (this != &other)
|
|
{
|
|
m_headers = std::move(other.m_headers);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a header field using the '<<' operator.
|
|
/// </summary>
|
|
/// <param name="name">The name of the header field.</param>
|
|
/// <param name="value">The value of the header field.</param>
|
|
/// <remarks>If the header field exists, the value will be combined as comma separated string.</remarks>
|
|
template<typename _t1>
|
|
void add(const key_type& name, const _t1& value)
|
|
{
|
|
auto printedValue = utility::conversions::details::print_string(value);
|
|
auto& mapVal = m_headers[name];
|
|
if (mapVal.empty())
|
|
{
|
|
mapVal = std::move(printedValue);
|
|
}
|
|
else
|
|
{
|
|
mapVal.append(_XPLATSTR(", ")).append(std::move(printedValue));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a header field.
|
|
/// </summary>
|
|
/// <param name="name">The name of the header field.</param>
|
|
void remove(const key_type& name) { m_headers.erase(name); }
|
|
|
|
/// <summary>
|
|
/// Removes all elements from the headers.
|
|
/// </summary>
|
|
void clear() { m_headers.clear(); }
|
|
|
|
/// <summary>
|
|
/// Checks if there is a header with the given key.
|
|
/// </summary>
|
|
/// <param name="name">The name of the header field.</param>
|
|
/// <returns><c>true</c> if there is a header with the given name, <c>false</c> otherwise.</returns>
|
|
bool has(const key_type& name) const { return m_headers.find(name) != m_headers.end(); }
|
|
|
|
/// <summary>
|
|
/// Returns the number of header fields.
|
|
/// </summary>
|
|
/// <returns>Number of header fields.</returns>
|
|
size_type size() const { return m_headers.size(); }
|
|
|
|
/// <summary>
|
|
/// Tests to see if there are any header fields.
|
|
/// </summary>
|
|
/// <returns><c>true</c> if there are no headers, <c>false</c> otherwise.</returns>
|
|
bool empty() const { return m_headers.empty(); }
|
|
|
|
/// <summary>
|
|
/// Returns a reference to header field with given name, if there is no header field one is inserted.
|
|
/// </summary>
|
|
utility::string_t& operator[](const key_type& name) { return m_headers[name]; }
|
|
|
|
/// <summary>
|
|
/// Checks if a header field exists with given name and returns an iterator if found. Otherwise
|
|
/// and iterator to end is returned.
|
|
/// </summary>
|
|
/// <param name="name">The name of the header field.</param>
|
|
/// <returns>An iterator to where the HTTP header is found.</returns>
|
|
iterator find(const key_type& name) { return m_headers.find(name); }
|
|
const_iterator find(const key_type& name) const { return m_headers.find(name); }
|
|
|
|
/// <summary>
|
|
/// Attempts to match a header field with the given name using the '>>' operator.
|
|
/// </summary>
|
|
/// <param name="name">The name of the header field.</param>
|
|
/// <param name="value">The value of the header field.</param>
|
|
/// <returns><c>true</c> if header field was found and successfully stored in value parameter.</returns>
|
|
template<typename _t1>
|
|
bool match(const key_type& name, _t1& value) const
|
|
{
|
|
auto iter = m_headers.find(name);
|
|
if (iter == m_headers.end())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return web::http::details::bind_impl(iter->second, value) || iter->second.empty();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an iterator referring to the first header field.
|
|
/// </summary>
|
|
/// <returns>An iterator to the beginning of the HTTP headers</returns>
|
|
iterator begin() { return m_headers.begin(); }
|
|
const_iterator begin() const { return m_headers.begin(); }
|
|
|
|
/// <summary>
|
|
/// Returns an iterator referring to the past-the-end header field.
|
|
/// </summary>
|
|
/// <returns>An iterator to the element past the end of the HTTP headers.</returns>
|
|
iterator end() { return m_headers.end(); }
|
|
const_iterator end() const { return m_headers.end(); }
|
|
|
|
/// <summary>
|
|
/// Gets the content length of the message.
|
|
/// </summary>
|
|
/// <returns>The length of the content.</returns>
|
|
_ASYNCRTIMP utility::size64_t content_length() const;
|
|
|
|
/// <summary>
|
|
/// Sets the content length of the message.
|
|
/// </summary>
|
|
/// <param name="length">The length of the content.</param>
|
|
_ASYNCRTIMP void set_content_length(utility::size64_t length);
|
|
|
|
/// <summary>
|
|
/// Gets the content type of the message.
|
|
/// </summary>
|
|
/// <returns>The content type of the body.</returns>
|
|
_ASYNCRTIMP utility::string_t content_type() const;
|
|
|
|
/// <summary>
|
|
/// Sets the content type of the message.
|
|
/// </summary>
|
|
/// <param name="type">The content type of the body.</param>
|
|
_ASYNCRTIMP void set_content_type(utility::string_t type);
|
|
|
|
/// <summary>
|
|
/// Gets the cache control header of the message.
|
|
/// </summary>
|
|
/// <returns>The cache control header value.</returns>
|
|
_ASYNCRTIMP utility::string_t cache_control() const;
|
|
|
|
/// <summary>
|
|
/// Sets the cache control header of the message.
|
|
/// </summary>
|
|
/// <param name="control">The cache control header value.</param>
|
|
_ASYNCRTIMP void set_cache_control(utility::string_t control);
|
|
|
|
/// <summary>
|
|
/// Gets the date header of the message.
|
|
/// </summary>
|
|
/// <returns>The date header value.</returns>
|
|
_ASYNCRTIMP utility::string_t date() const;
|
|
|
|
/// <summary>
|
|
/// Sets the date header of the message.
|
|
/// </summary>
|
|
/// <param name="date">The date header value.</param>
|
|
_ASYNCRTIMP void set_date(const utility::datetime& date);
|
|
|
|
private:
|
|
// Headers are stored in a map with case insensitive key.
|
|
inner_container m_headers;
|
|
};
|
|
} // namespace http
|
|
} // namespace web
|