| 1127 | } |
| 1128 | |
| 1129 | server_http_proxy::server_http_proxy( |
| 1130 | const std::string & method, |
| 1131 | const std::string & scheme, |
| 1132 | const std::string & host, |
| 1133 | int port, |
| 1134 | const std::string & path, |
| 1135 | const std::map<std::string, std::string> & headers, |
| 1136 | const std::string & body, |
| 1137 | const std::function<bool()> should_stop, |
| 1138 | int32_t timeout_read, |
| 1139 | int32_t timeout_write |
| 1140 | ) { |
| 1141 | // shared between reader and writer threads |
| 1142 | auto cli = std::make_shared<httplib::ClientImpl>(host, port); |
| 1143 | auto pipe = std::make_shared<pipe_t<msg_t>>(); |
| 1144 | |
| 1145 | if (scheme == "https") { |
| 1146 | #ifdef CPPHTTPLIB_OPENSSL_SUPPORT |
| 1147 | cli.reset(new httplib::SSLClient(host, port)); |
| 1148 | #else |
| 1149 | throw std::runtime_error("HTTPS requested but CPPHTTPLIB_OPENSSL_SUPPORT is not defined"); |
| 1150 | #endif |
| 1151 | } |
| 1152 | |
| 1153 | // setup Client |
| 1154 | cli->set_follow_location(true); |
| 1155 | cli->set_connection_timeout(timeout_read, 0); // use --timeout value instead of hardcoded 5 s |
| 1156 | cli->set_write_timeout(timeout_read, 0); // reversed for cli (client) vs srv (server) |
| 1157 | cli->set_read_timeout(timeout_write, 0); |
| 1158 | this->status = 500; // to be overwritten upon response |
| 1159 | this->cleanup = [pipe]() { |
| 1160 | pipe->close_read(); |
| 1161 | pipe->close_write(); |
| 1162 | }; |
| 1163 | |
| 1164 | // wire up the receive end of the pipe |
| 1165 | this->next = [pipe, should_stop](std::string & out) -> bool { |
| 1166 | msg_t msg; |
| 1167 | bool has_next = pipe->read(msg, should_stop); |
| 1168 | if (!msg.data.empty()) { |
| 1169 | out = std::move(msg.data); |
| 1170 | } |
| 1171 | return has_next; // false if EOF or pipe broken |
| 1172 | }; |
| 1173 | |
| 1174 | // wire up the HTTP client |
| 1175 | // note: do NOT capture `this` pointer, as it may be destroyed before the thread ends |
| 1176 | httplib::ResponseHandler response_handler = [pipe, cli](const httplib::Response & response) { |
| 1177 | msg_t msg; |
| 1178 | msg.status = response.status; |
| 1179 | for (const auto & [key, value] : response.headers) { |
| 1180 | const auto lowered = to_lower_copy(key); |
| 1181 | if (should_strip_proxy_header(lowered)) { |
| 1182 | continue; |
| 1183 | } |
| 1184 | if (lowered == "content-type") { |
| 1185 | msg.content_type = value; |
| 1186 | continue; |
nothing calls this directly
no test coverage detected