/*** * 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 #include #include #include #include namespace web { namespace http { /// /// Binds an individual reference to a string value. /// /// The type of string value. /// The type of the value to bind to. /// The string value. /// The value to bind to. /// true if the binding succeeds, false otherwise. template 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; } /// /// Binds an individual reference to a string value. /// This specialization is need because istringstream::>> delimits on whitespace. /// /// The type of the string value. /// The string value. /// The value to bind to. /// true if the binding succeeds, false otherwise. template 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 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 bool bind_impl(const key_type& text, utf16string& ref) { ref = utility::conversions::to_utf16string(text); return true; } template bool bind_impl(const key_type& text, std::string& ref) { ref = utility::conversions::to_utf8string(text); return true; } } // namespace details /// /// Represents HTTP headers, acts like a map. /// 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 inner_container; public: /// /// STL-style typedefs /// 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; /// /// Constructs an empty set of HTTP headers. /// http_headers() {} /// /// Copy constructor. /// /// An http_headers object to copy from. http_headers(const http_headers& other) : m_headers(other.m_headers) {} /// /// Assignment operator. /// /// An http_headers object to copy from. http_headers& operator=(const http_headers& other) { if (this != &other) { m_headers = other.m_headers; } return *this; } /// /// Move constructor. /// /// An http_headers object to move. http_headers(http_headers&& other) : m_headers(std::move(other.m_headers)) {} /// /// Move assignment operator. /// /// An http_headers object to move. http_headers& operator=(http_headers&& other) { if (this != &other) { m_headers = std::move(other.m_headers); } return *this; } /// /// Adds a header field using the '<<' operator. /// /// The name of the header field. /// The value of the header field. /// If the header field exists, the value will be combined as comma separated string. template 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)); } } /// /// Removes a header field. /// /// The name of the header field. void remove(const key_type& name) { m_headers.erase(name); } /// /// Removes all elements from the headers. /// void clear() { m_headers.clear(); } /// /// Checks if there is a header with the given key. /// /// The name of the header field. /// true if there is a header with the given name, false otherwise. bool has(const key_type& name) const { return m_headers.find(name) != m_headers.end(); } /// /// Returns the number of header fields. /// /// Number of header fields. size_type size() const { return m_headers.size(); } /// /// Tests to see if there are any header fields. /// /// true if there are no headers, false otherwise. bool empty() const { return m_headers.empty(); } /// /// Returns a reference to header field with given name, if there is no header field one is inserted. /// utility::string_t& operator[](const key_type& name) { return m_headers[name]; } /// /// Checks if a header field exists with given name and returns an iterator if found. Otherwise /// and iterator to end is returned. /// /// The name of the header field. /// An iterator to where the HTTP header is found. iterator find(const key_type& name) { return m_headers.find(name); } const_iterator find(const key_type& name) const { return m_headers.find(name); } /// /// Attempts to match a header field with the given name using the '>>' operator. /// /// The name of the header field. /// The value of the header field. /// true if header field was found and successfully stored in value parameter. template 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(); } /// /// Returns an iterator referring to the first header field. /// /// An iterator to the beginning of the HTTP headers iterator begin() { return m_headers.begin(); } const_iterator begin() const { return m_headers.begin(); } /// /// Returns an iterator referring to the past-the-end header field. /// /// An iterator to the element past the end of the HTTP headers. iterator end() { return m_headers.end(); } const_iterator end() const { return m_headers.end(); } /// /// Gets the content length of the message. /// /// The length of the content. _ASYNCRTIMP utility::size64_t content_length() const; /// /// Sets the content length of the message. /// /// The length of the content. _ASYNCRTIMP void set_content_length(utility::size64_t length); /// /// Gets the content type of the message. /// /// The content type of the body. _ASYNCRTIMP utility::string_t content_type() const; /// /// Sets the content type of the message. /// /// The content type of the body. _ASYNCRTIMP void set_content_type(utility::string_t type); /// /// Gets the cache control header of the message. /// /// The cache control header value. _ASYNCRTIMP utility::string_t cache_control() const; /// /// Sets the cache control header of the message. /// /// The cache control header value. _ASYNCRTIMP void set_cache_control(utility::string_t control); /// /// Gets the date header of the message. /// /// The date header value. _ASYNCRTIMP utility::string_t date() const; /// /// Sets the date header of the message. /// /// The date header value. _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