1 /*** 2 * Copyright (C) Microsoft. All rights reserved. 3 * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. 4 * 5 * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 6 * 7 * HTTP Library: Client-side APIs. 8 * 9 * For the latest on this and related APIs, please see: https://github.com/Microsoft/cpprestsdk 10 * 11 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 12 ****/ 13 #pragma once 14 15 #include "cpprest/astreambuf.h" 16 #include "cpprest/details/basic_types.h" 17 #include "cpprest/http_client.h" 18 #include "cpprest/http_msg.h" 19 #include <memory> 20 #include <stdexcept> 21 #include <string> 22 23 namespace web 24 { 25 namespace http 26 { 27 namespace details 28 { 29 /// <summary> 30 /// Serialize the http_headers into name:value pairs separated by a carriage return and line feed. 31 /// </summary> 32 utility::string_t flatten_http_headers(const http_headers& headers); 33 /// <summary> 34 /// Parses a string containing Http headers. 35 /// </summary> 36 void parse_headers_string(_Inout_z_ utility::char_t* headersStr, http_headers& headers); 37 } // namespace details 38 } // namespace http 39 } // namespace web 40 41 namespace web 42 { 43 namespace http 44 { 45 namespace client 46 { 47 namespace details 48 { 49 class _http_client_communicator; 50 51 // Request context encapsulating everything necessary for creating and responding to a request. 52 class request_context 53 { 54 public: 55 // Destructor to clean up any held resources. ~request_context()56 virtual ~request_context() {} 57 58 virtual void report_exception(std::exception_ptr exceptionPtr); 59 60 virtual concurrency::streams::streambuf<uint8_t> _get_readbuffer(); 61 62 void complete_headers(); 63 64 /// <summary> 65 /// Completes this request, setting the underlying task completion event, and cleaning up the handles 66 /// </summary> 67 void complete_request(utility::size64_t body_size); 68 69 void report_error(unsigned long error_code, const std::string& errorMessage); 70 71 #ifdef _WIN32 72 void report_error(unsigned long error_code, const std::wstring& errorMessage); 73 #endif 74 75 template<typename _ExceptionType> report_exception(const _ExceptionType & e)76 void report_exception(const _ExceptionType& e) 77 { 78 report_exception(std::make_exception_ptr(e)); 79 } 80 81 /// <summary>Set m_decompressor based on the response headers, or call report_exception</summary> 82 /// <returns>false on failure</returns> 83 bool handle_compression(); 84 85 /// <summary>Append an Accept-Encoding header if requested by the http_client settings</summary> 86 utility::string_t get_compression_header() const; 87 88 concurrency::streams::streambuf<uint8_t> _get_writebuffer(); 89 90 // Reference to the http_client implementation. 91 std::shared_ptr<_http_client_communicator> m_http_client; 92 93 // request/response pair. 94 http_request m_request; 95 http_response m_response; 96 97 utility::size64_t m_uploaded; 98 utility::size64_t m_downloaded; 99 100 // task completion event to signal request is completed. 101 pplx::task_completion_event<http_response> m_request_completion; 102 103 // Registration for cancellation notification if enabled. 104 pplx::cancellation_token_registration m_cancellationRegistration; 105 106 std::unique_ptr<web::http::compression::decompress_provider> m_decompressor; 107 108 protected: 109 request_context(const std::shared_ptr<_http_client_communicator>& client, const http_request& request); 110 111 virtual void finish(); 112 }; 113 114 // 115 // Interface used by client implementations. Concrete implementations are responsible for 116 // sending HTTP requests and receiving the responses. 117 // 118 class _http_client_communicator : public http_pipeline_stage 119 { 120 public: 121 virtual ~_http_client_communicator() override = default; 122 123 // Asynchronously send a HTTP request and process the response. 124 void async_send_request(const std::shared_ptr<request_context>& request); 125 126 void finish_request(); 127 128 const http_client_config& client_config() const; 129 130 const uri& base_uri() const; 131 132 protected: 133 _http_client_communicator(http::uri&& address, http_client_config&& client_config); 134 135 // HTTP client implementations must implement send_request. 136 virtual void send_request(_In_ const std::shared_ptr<request_context>& request) = 0; 137 138 // URI to connect to. 139 const http::uri m_uri; 140 141 pplx::extensibility::critical_section_t m_client_lock; 142 143 private: 144 http_client_config m_client_config; 145 146 // Wraps opening the client around sending a request. 147 void async_send_request_impl(const std::shared_ptr<request_context>& request); 148 149 // Queue used to guarantee ordering of requests, when applicable. 150 std::queue<std::shared_ptr<request_context>> m_requests_queue; 151 bool m_outstanding; 152 }; 153 154 /// <summary> 155 /// Factory function implemented by the separate platforms to construct their subclasses of _http_client_communicator 156 /// </summary> 157 std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, 158 http_client_config&& client_config); 159 160 } // namespace details 161 } // namespace client 162 } // namespace http 163 } // namespace web 164