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 HTTP_MOCK_SERVER_HPP
18 #define HTTP_MOCK_SERVER_HPP
19 
20 #define HTTP_MOCK_HOSTNAME "cpp-driver.hostname."
21 #define HTTP_MOCK_SERVER_IP "127.254.254.254"
22 #define HTTP_MOCK_SERVER_PORT 30443
23 
24 #include "http_parser.h"
25 #include "mockssandra.hpp"
26 #include "string.hpp"
27 
28 namespace mockssandra { namespace http {
29 
30 /**
31  * Mockssandra HTTP server.
32  *
33  * If no response body is set then the default response will the be original request; e.g. echo HTTP
34  * server.
35  */
36 class Server {
37 public:
Server()38   Server()
39       : path_("/")
40       , content_type_("text/plain")
41       , response_status_code_(200)
42       , enable_valid_response_(true)
43       , close_connnection_after_request_(true)
44       , event_loop_group_(1, "HTTP Server")
45       , factory_(this)
46       , server_connection_(new internal::ServerConnection(
47             Address(HTTP_MOCK_SERVER_IP, HTTP_MOCK_SERVER_PORT), factory_)) {}
48 
path() const49   const String& path() const { return path_; }
content_type() const50   const String& content_type() const { return content_type_; }
response_body() const51   const String& response_body() const { return response_body_; }
response_status_code() const52   int response_status_code() const { return response_status_code_; }
enable_valid_response()53   bool enable_valid_response() { return enable_valid_response_; }
close_connnection_after_request()54   bool close_connnection_after_request() { return close_connnection_after_request_; }
55 
set_path(const String & path)56   void set_path(const String& path) { path_ = path; }
set_content_type(const String & content_type)57   void set_content_type(const String& content_type) { content_type_ = content_type; }
set_response_body(const String & response_body)58   void set_response_body(const String& response_body) { response_body_ = response_body; }
set_response_status_code(int status_code)59   void set_response_status_code(int status_code) { response_status_code_ = status_code; }
enable_valid_response(bool enable)60   void enable_valid_response(bool enable) { enable_valid_response_ = enable; }
set_close_connnection_after_request(bool enable)61   void set_close_connnection_after_request(bool enable) {
62     close_connnection_after_request_ = enable;
63   }
64 
65   bool use_ssl(const String& key, const String& cert, const String& ca_cert = "",
66                bool require_client_cert = false);
67 
68   void listen();
69   void close();
70 
71 private:
72   class ClientConnection : public internal::ClientConnection {
73   public:
74     ClientConnection(internal::ServerConnection* server_connection, Server* server);
75 
76     virtual void on_read(const char* data, size_t len);
77 
78   private:
79     static int on_url(http_parser* parser, const char* buf, size_t len);
80     void handle_url(const char* buf, size_t len);
81 
82   private:
83     String path_;
84     String content_type_;
85     String response_body_;
86     int response_status_code_;
87     bool enable_valid_response_;
88     bool close_connnection_after_request_;
89     String request_;
90     http_parser parser_;
91     http_parser_settings parser_settings_;
92   };
93 
94   class ClientConnectionFactory : public internal::ClientConnectionFactory {
95   public:
ClientConnectionFactory(Server * server)96     ClientConnectionFactory(Server* server)
97         : server_(server) {}
98 
99     virtual internal::ClientConnection*
create(internal::ServerConnection * server_connection) const100     create(internal::ServerConnection* server_connection) const {
101       return new ClientConnection(server_connection, server_);
102     }
103 
104   private:
105     Server* const server_;
106   };
107 
108 private:
109   String path_;
110   String content_type_;
111   String response_body_;
112   int response_status_code_;
113   bool enable_valid_response_;
114   bool close_connnection_after_request_;
115   SimpleEventLoopGroup event_loop_group_;
116   ClientConnectionFactory factory_;
117   internal::ServerConnection::Ptr server_connection_;
118 };
119 
120 }} // namespace mockssandra::http
121 
122 #endif
123