1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #ifndef DATASTAX_INTERNAL_HTTP_CLIENT_HPP
18 #define DATASTAX_INTERNAL_HTTP_CLIENT_HPP
19 
20 #include "address.hpp"
21 #include "callback.hpp"
22 #include "cloud_secure_connection_config.hpp"
23 #include "event_loop.hpp"
24 #include "http_parser.h"
25 #include "ref_counted.hpp"
26 #include "socket_connector.hpp"
27 #include "string.hpp"
28 
29 namespace datastax { namespace internal { namespace core {
30 
31 class HttpClient : public RefCounted<HttpClient> {
32 public:
33   typedef SharedRefPtr<HttpClient> Ptr;
34   typedef internal::Callback<void, HttpClient*> Callback;
35 
36   enum HttpClientError {
37     HTTP_CLIENT_OK,
38     HTTP_CLIENT_CANCELED,
39     HTTP_CLIENT_ERROR_SOCKET,
40     HTTP_CLIENT_ERROR_PARSING,
41     HTTP_CLIENT_ERROR_HTTP_STATUS,
42     HTTP_CLIENT_ERROR_TIMEOUT,
43     HTTP_CLIENT_ERROR_CLOSED
44   };
45 
46   HttpClient(const Address& address, const String& path, const Callback& callback);
47 
48   HttpClient* with_settings(const SocketSettings& settings);
49 
50   HttpClient* with_request_timeout_ms(uint64_t request_timeout_ms);
51 
is_ok() const52   bool is_ok() const { return error_code_ == HTTP_CLIENT_OK; }
is_error_status_code() const53   bool is_error_status_code() const { return error_code_ == HTTP_CLIENT_ERROR_HTTP_STATUS; }
is_canceled() const54   bool is_canceled() const { return error_code_ == HTTP_CLIENT_CANCELED; }
error_code() const55   HttpClientError error_code() const { return error_code_; }
error_message() const56   String error_message() const { return error_message_; }
status_code() const57   unsigned status_code() const { return status_code_; }
content_type() const58   const String& content_type() const { return content_type_; }
response_body() const59   const String& response_body() const { return response_body_; }
60 
61   void request(uv_loop_t* loop);
62   void cancel();
63 
64 private:
65   friend class HttpClientSocketHandler;
66   friend class HttpClientSslSocketHandler;
67 
68 private:
69   void on_socket_connect(SocketConnector* connector);
70   void on_read(char* buf, ssize_t nread);
71   void on_timeout(Timer* timer);
72 
73   static int on_status(http_parser* parser, const char* buf, size_t len);
74   int handle_status(unsigned status_code);
75   static int on_header_field(http_parser* parser, const char* buf, size_t len);
76   int handle_header_field(const char* buf, size_t len);
77   static int on_header_value(http_parser* parser, const char* buf, size_t len);
78   int handle_header_value(const char* buf, size_t len);
79   static int on_body(http_parser* parser, const char* buf, size_t len);
80   int handle_body(const char* buf, size_t len);
81   static int on_message_complete(http_parser* parser);
82   int handle_message_complete();
83 
84   void finish();
85 
86 private:
87   HttpClientError error_code_;
88   String error_message_;
89   Address address_;
90   String path_;
91   Callback callback_;
92   SocketConnector::Ptr socket_connector_;
93   Socket::Ptr socket_;
94   Timer request_timer_;
95   uint64_t request_timeout_ms_;
96   http_parser parser_;
97   http_parser_settings parser_settings_;
98   String current_header_;
99   unsigned status_code_;
100   String content_type_;
101   String response_body_;
102 };
103 
104 }}} // namespace datastax::internal::core
105 
106 #endif
107