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