mirror of
https://github.com/SantaSpeen/BeamMP-Server.git
synced 2026-04-03 15:16:01 +00:00
Multiple merge fixes, rebase, working Https::GET
This commit is contained in:
104
src/Http.cpp
104
src/Http.cpp
@@ -15,94 +15,7 @@ namespace net = boost::asio; // from <boost/asio.hpp>
|
||||
namespace ssl = net::ssl; // from <boost/asio/ssl.hpp>
|
||||
using tcp = net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
||||
|
||||
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
|
||||
|
||||
|
||||
try {
|
||||
// Check command line arguments.
|
||||
int version = 11;
|
||||
|
||||
|
||||
|
||||
|
||||
// The io_context is required for all I/O
|
||||
net::io_context ioc;
|
||||
|
||||
// The SSL context is required, and holds certificates
|
||||
ssl::context ctx(ssl::context::tlsv12_client);
|
||||
|
||||
// This holds the root certificate used for verification
|
||||
// we don't do / have this
|
||||
// load_root_certificates(ctx);
|
||||
|
||||
// Verify the remote server's certificate
|
||||
ctx.set_verify_mode(ssl::verify_none);
|
||||
|
||||
// These objects perform our I/O
|
||||
tcp::resolver resolver(ioc);
|
||||
beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
|
||||
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) {
|
||||
beast::error_code ec { static_cast<int>(::ERR_get_error()), net::error::get_ssl_category() };
|
||||
throw beast::system_error { ec };
|
||||
}
|
||||
|
||||
// Look up the domain name
|
||||
auto const results = resolver.resolve(host.c_str(), std::to_string(port));
|
||||
|
||||
// Make the connection on the IP address we get from a lookup
|
||||
beast::get_lowest_layer(stream).connect(results);
|
||||
|
||||
// Perform the SSL handshake
|
||||
stream.handshake(ssl::stream_base::client);
|
||||
|
||||
// Set up an HTTP GET request message
|
||||
http::request<http::string_body> req { http::verb::get, target, version };
|
||||
req.set(http::field::host, host);
|
||||
|
||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||
|
||||
// Send the HTTP request to the remote host
|
||||
http::write(stream, req);
|
||||
|
||||
// This buffer is used for reading and must be persisted
|
||||
beast::flat_buffer buffer;
|
||||
|
||||
|
||||
|
||||
|
||||
// Declare a container to hold the response
|
||||
http::response<http::string_body> res;
|
||||
|
||||
// Receive the HTTP response
|
||||
http::read(stream, buffer, res);
|
||||
|
||||
// Gracefully close the stream
|
||||
beast::error_code ec;
|
||||
stream.shutdown(ec);
|
||||
if (ec == net::error::eof) {
|
||||
// Rationale:
|
||||
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
|
||||
ec = {};
|
||||
}
|
||||
|
||||
if (status) {
|
||||
*status = res.base().result_int();
|
||||
}
|
||||
|
||||
if (ec)
|
||||
throw beast::system_error { ec };
|
||||
|
||||
// If we get here then the connection is closed gracefully
|
||||
return std::string(res.body());
|
||||
} catch (std::exception const& e) {
|
||||
Application::Console().Write(__func__ + std::string(": ") + e.what());
|
||||
return ErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
std::string GenericRequest(http::verb verb, const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
try {
|
||||
net::io_context io;
|
||||
|
||||
@@ -140,14 +53,13 @@ std::string Http::POST(const std::string& host, int port, const std::string& tar
|
||||
}
|
||||
//}
|
||||
stream.handshake(ssl::stream_base::client);
|
||||
http::request<http::string_body> req { http::verb::post, target, 11 /* http 1.1 */ };
|
||||
http::request<http::string_body> req { verb, target, 11 /* http 1.1 */ };
|
||||
|
||||
req.set(http::field::host, host);
|
||||
if (!body.empty()) {
|
||||
req.set(http::field::content_type, ContentType); // "application/json"
|
||||
// "application/x-www-form-urlencoded"
|
||||
|
||||
|
||||
req.set(http::field::content_length, std::to_string(body.size()));
|
||||
req.body() = body;
|
||||
// info("body is " + body + " (" + req.body() + ")");
|
||||
@@ -215,10 +127,18 @@ std::string Http::POST(const std::string& host, int port, const std::string& tar
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
Application::Console().Write(__func__ + std::string(": ") + e.what());
|
||||
return ErrorString;
|
||||
return Http::ErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Http::GET(const std::string& host, int port, const std::string& target, unsigned int* status) {
|
||||
return GenericRequest(http::verb::get, host, port, target, {}, {}, {}, status);
|
||||
}
|
||||
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::unordered_map<std::string, std::string>& fields, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
return GenericRequest(http::verb::post, host, port, target, fields, body, ContentType, status);
|
||||
}
|
||||
|
||||
// RFC 2616, RFC 7231
|
||||
static std::map<size_t, const char*> Map = {
|
||||
{ 100, "Continue" },
|
||||
@@ -291,4 +211,4 @@ std::string Http::Status::ToString(int code) {
|
||||
} else {
|
||||
return "Unassigned";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user