std::string request(http::client &client, http::method method, const string &userPath) { char buf[http::MAX_URL_LEN + 1] = {0}; buffered_socket sock; std::string path = userPath; net::uri uri = client.uri(); std::string content = client.content(); if (client.is_secure()) { sock.set_secure(true); } if (!uri.port().empty()) { int port = stoi(uri.port()); if (!sock.connect(uri.host(), port)) { throw socket_exception("unable to connect to " + uri.to_string()); } } else { if (!sock.connect(uri.host(), client.is_secure() ? http::DEFAULT_SECURE_PORT : http::DEFAULT_PORT)) { throw socket_exception("unable to connect to " + uri.to_string()); } } if (path.empty()) { path = uri.full_path(); } // send the method and path if (path.empty()) snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], "/", client.version().c_str()); else if (path[0] == '/') snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], path.c_str(), client.version().c_str()); else snprintf(buf, http::MAX_URL_LEN, http::REQUEST_PREAMBLE, http::method_names[method], ("/" + path).c_str(), client.version().c_str()); sock.writeln(buf); bool chunked = client.has_header(http::HEADER_TRANSFER_ENCODING) && !strcasecmp(client.header(http::HEADER_TRANSFER_ENCODING).c_str(), "chunked"); // specify the host if (!client.has_header(http::HEADER_HOST)) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", http::HEADER_HOST, uri.host().c_str()); sock.writeln(buf); } if (!client.has_header(http::HEADER_ACCEPT)) { snprintf(buf, http::MAX_URL_LEN, "%s: */*", http::HEADER_ACCEPT); sock.writeln(buf); } if (!client.has_header(http::HEADER_CONNECTION)) { snprintf(buf, http::MAX_URL_LEN, "%s: close", http::HEADER_CONNECTION); sock.writeln(buf); } // add the headers for (const auto &h : client.headers()) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", h.first.c_str(), h.second.c_str()); sock.writeln(buf); } // if we have a content, add the size if (!chunked && !content.empty()) { snprintf(buf, http::MAX_URL_LEN, "%s: %zu", http::HEADER_CONTENT_SIZE, content.size()); sock.writeln(buf); } // finish header sock.writeln(); // add the content if (!content.empty()) { sock.write(content); } #ifdef DEBUG cout << string(sock.output().begin(), sock.output().end()); #endif if (!sock.write_from_buffer()) { throw socket_exception("unable to write to socket"); } if (!sock.read_to_buffer()) { throw socket_exception("unable to read from socket"); } auto input = sock.input(); return string(input.begin(), input.end()); }
std::string request(http::client &client, http::method method, const std::string &userPath) { CURLcode code; char buf[http::MAX_URL_LEN + 1] = {0}; struct curl_slist *headers = NULL; CURL *curl = NULL; std::string path = userPath; net::uri uri = client.uri(); std::string content = client.content(); std::string response; curl = curl_easy_init(); if (curl == NULL) { throw socket_exception("unable to initialize curl request"); } // check if a path was specified if (path.empty()) { path = uri.full_path(); } if (path.empty()) { snprintf(buf, http::MAX_URL_LEN, "%s://%s", uri.scheme().c_str(), uri.host_with_port().c_str()); } else if (path[0] == '/') { snprintf(buf, http::MAX_URL_LEN, "%s://%s%s", uri.scheme().c_str(), uri.host_with_port().c_str(), path.c_str()); } else { snprintf(buf, http::MAX_URL_LEN, "%s://%s/%s", uri.scheme().c_str(), uri.host_with_port().c_str(), path.c_str()); } helper::curl_set_opt(curl, CURLOPT_URL, buf); helper::curl_set_opt_fun(curl, CURLOPT_WRITEFUNCTION, helper::curl_append_response_callback); helper::curl_set_opt_num(curl, CURLOPT_HEADER, 1L); #ifdef DEBUG helper::curl_set_opt_num(curl, CURLOPT_VERBOSE, 1L); #endif switch (method) { case http::GET: helper::curl_set_opt_num(curl, CURLOPT_HTTPGET, 1L); break; case http::POST: helper::curl_set_opt_num(curl, CURLOPT_POST, 1L); if (!content.empty()) { helper::curl_set_opt(curl, CURLOPT_POSTFIELDS, content.c_str()); helper::curl_set_opt_num(curl, CURLOPT_POSTFIELDSIZE, content.size()); } break; case http::PUT: helper::curl_set_opt_num(curl, CURLOPT_PUT, 1L); if (!content.empty()) { helper::curl_set_opt(curl, CURLOPT_POSTFIELDS, content.c_str()); helper::curl_set_opt_num(curl, CURLOPT_POSTFIELDSIZE, content.size()); } break; default: helper::curl_set_opt(curl, CURLOPT_CUSTOMREQUEST, http::method_names[method]); break; } for (auto &h : client.headers()) { snprintf(buf, http::MAX_URL_LEN, "%s: %s", h.first.c_str(), h.second.c_str()); headers = curl_slist_append(headers, buf); } helper::curl_set_opt(curl, CURLOPT_HTTPHEADER, headers); helper::curl_set_opt_num(curl, CURLOPT_TIMEOUT, client.timeout()); helper::curl_set_opt(curl, CURLOPT_WRITEDATA, &response); CURLcode res = curl_easy_perform(curl); curl_slist_free_all(headers); if (res != CURLE_OK && res != CURLE_PARTIAL_FILE) { curl_easy_cleanup(curl); throw socket_exception(curl_easy_strerror(res)); } curl_easy_cleanup(curl); return response; }