Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow changing of HTTP protocol to 1.0 for backwards API endpoints and broken servers #951

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions include/dpp/cluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -1325,8 +1325,9 @@ class DPP_EXPORT cluster {
* @param filename Filename to post for POST requests (for uploading files)
* @param filecontent File content to post for POST requests (for uploading files)
* @param filemimetype File content to post for POST requests (for uploading files)
* @param protocol HTTP protocol to use (1.0 and 1.1 are supported)
*/
void post_rest(const std::string &endpoint, const std::string &major_parameters, const std::string &parameters, http_method method, const std::string &postdata, json_encode_t callback, const std::string &filename = "", const std::string &filecontent = "", const std::string &filemimetype = "");
void post_rest(const std::string &endpoint, const std::string &major_parameters, const std::string &parameters, http_method method, const std::string &postdata, json_encode_t callback, const std::string &filename = "", const std::string &filecontent = "", const std::string &filemimetype = "", const std::string& protocol = "1.1");

/**
* @brief Post a multipart REST request. Where possible use a helper method instead like message_create
Expand All @@ -1352,8 +1353,9 @@ class DPP_EXPORT cluster {
* @param postdata POST data
* @param mimetype MIME type of POST data
* @param headers Headers to send with the request
* @param protocol HTTP protocol to use (1.1 and 1.0 are supported)
*/
void request(const std::string &url, http_method method, http_completion_event callback, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap<std::string, std::string> &headers = {});
void request(const std::string &url, http_method method, http_completion_event callback, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap<std::string, std::string> &headers = {}, const std::string &protocol = "1.1");

/**
* @brief Respond to a slash command
Expand Down
8 changes: 7 additions & 1 deletion include/dpp/httpsclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ class DPP_EXPORT https_client : public ssl_client
*/
uint16_t status;

/**
* @brief The HTTP protocol to use
*/
std::string http_protocol;

/**
* @brief Time at which the request should be abandoned
*/
Expand Down Expand Up @@ -243,8 +248,9 @@ class DPP_EXPORT https_client : public ssl_client
* @param extra_headers Additional request headers, e.g. user-agent, authorization, etc
* @param plaintext_connection Set to true to make the connection plaintext (turns off SSL)
* @param request_timeout How many seconds before the connection is considered failed if not finished
* @param http_protocol Request HTTP protocol
*/
https_client(const std::string &hostname, uint16_t port = 443, const std::string &urlpath = "/", const std::string &verb = "GET", const std::string &req_body = "", const http_headers& extra_headers = {}, bool plaintext_connection = false, uint16_t request_timeout = 5);
https_client(const std::string &hostname, uint16_t port = 443, const std::string &urlpath = "/", const std::string &verb = "GET", const std::string &req_body = "", const http_headers& extra_headers = {}, bool plaintext_connection = false, uint16_t request_timeout = 5, const std::string &protocol = "1.1");

/**
* @brief Destroy the https client object
Expand Down
11 changes: 8 additions & 3 deletions include/dpp/queues.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ class DPP_EXPORT http_request {
std::multimap<std::string, std::string> req_headers;
/** @brief Waiting for rate limit to expire */
bool waiting;
/** @brief HTTP protocol */
std::string protocol;

/**
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
Expand All @@ -170,8 +172,9 @@ class DPP_EXPORT http_request {
* @param filename The filename (server side) of any uploaded file
* @param filecontent The binary content of any uploaded file for the request
* @param filemimetype The MIME type of any uploaded file for the request
* @param http_protocol HTTP protocol
*/
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::string &filename = "", const std::string &filecontent = "", const std::string &filemimetype = "");
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::string &filename = "", const std::string &filecontent = "", const std::string &filemimetype = "", const std::string &http_protocol = "1.1");

/**
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
Expand All @@ -184,8 +187,9 @@ class DPP_EXPORT http_request {
* @param filename The filename (server side) of any uploaded file
* @param filecontent The binary content of any uploaded file for the request
* @param filemimetypes The MIME type of any uploaded file for the request
* @param http_protocol HTTP protocol
*/
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::vector<std::string> &filename = {}, const std::vector<std::string> &filecontent = {}, const std::vector<std::string> &filemimetypes = {});
http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata = "", http_method method = m_get, const std::string &audit_reason = "", const std::vector<std::string> &filename = {}, const std::vector<std::string> &filecontent = {}, const std::vector<std::string> &filemimetypes = {}, const std::string &http_protocol = "1.1");

/**
* @brief Constructor. When constructing one of these objects it should be passed to request_queue::post_request().
Expand All @@ -195,8 +199,9 @@ class DPP_EXPORT http_request {
* @param _postdata Data to send in POST and PUT requests
* @param _mimetype POST data mime type
* @param _headers HTTP headers to send
* @param http_protocol HTTP protocol
*/
http_request(const std::string &_url, http_completion_event completion, http_method method = m_get, const std::string &_postdata = "", const std::string &_mimetype = "text/plain", const std::multimap<std::string, std::string> &_headers = {});
http_request(const std::string &_url, http_completion_event completion, http_method method = m_get, const std::string &_postdata = "", const std::string &_mimetype = "text/plain", const std::multimap<std::string, std::string> &_headers = {}, const std::string &http_protocol = "1.1");

/**
* @brief Destroy the http request object
Expand Down
8 changes: 4 additions & 4 deletions src/dpp/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ json error_response(const std::string& message, http_request_completion_t& rv)
return j;
}

void cluster::post_rest(const std::string &endpoint, const std::string &major_parameters, const std::string &parameters, http_method method, const std::string &postdata, json_encode_t callback, const std::string &filename, const std::string &filecontent, const std::string &filemimetype) {
void cluster::post_rest(const std::string &endpoint, const std::string &major_parameters, const std::string &parameters, http_method method, const std::string &postdata, json_encode_t callback, const std::string &filename, const std::string &filecontent, const std::string &filemimetype, const std::string &protocol) {
/* NOTE: This is not a memory leak! The request_queue will free the http_request once it reaches the end of its lifecycle */
rest->post_request(new http_request(endpoint + (!major_parameters.empty() ? "/" : "") + major_parameters, parameters, [endpoint, callback](http_request_completion_t rv) {
json j;
Expand All @@ -314,7 +314,7 @@ void cluster::post_rest(const std::string &endpoint, const std::string &major_pa
if (callback) {
callback(j, rv);
}
}, postdata, method, get_audit_reason(), filename, filecontent, filemimetype));
}, postdata, method, get_audit_reason(), filename, filecontent, filemimetype, protocol));
}

void cluster::post_rest_multipart(const std::string &endpoint, const std::string &major_parameters, const std::string &parameters, http_method method, const std::string &postdata, json_encode_t callback, const std::vector<std::string> &filename, const std::vector<std::string> &filecontent, const std::vector<std::string> &filemimetypes) {
Expand All @@ -336,9 +336,9 @@ void cluster::post_rest_multipart(const std::string &endpoint, const std::string
}


void cluster::request(const std::string &url, http_method method, http_completion_event callback, const std::string &postdata, const std::string &mimetype, const std::multimap<std::string, std::string> &headers) {
void cluster::request(const std::string &url, http_method method, http_completion_event callback, const std::string &postdata, const std::string &mimetype, const std::multimap<std::string, std::string> &headers, const std::string &protocol) {
/* NOTE: This is not a memory leak! The request_queue will free the http_request once it reaches the end of its lifecycle */
raw_rest->post_request(new http_request(url, callback, method, postdata, mimetype, headers));
raw_rest->post_request(new http_request(url, callback, method, postdata, mimetype, headers, protocol));
}

gateway::gateway() : shards(0), session_start_total(0), session_start_remaining(0), session_start_reset_after(0), session_start_max_concurrency(0) {
Expand Down
5 changes: 3 additions & 2 deletions src/dpp/httpsclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

namespace dpp {

https_client::https_client(const std::string &hostname, uint16_t port, const std::string &urlpath, const std::string &verb, const std::string &req_body, const http_headers& extra_headers, bool plaintext_connection, uint16_t request_timeout)
https_client::https_client(const std::string &hostname, uint16_t port, const std::string &urlpath, const std::string &verb, const std::string &req_body, const http_headers& extra_headers, bool plaintext_connection, uint16_t request_timeout, const std::string &protocol)
: ssl_client(hostname, std::to_string(port), plaintext_connection, false),
state(HTTPS_HEADERS),
request_type(verb),
Expand All @@ -41,6 +41,7 @@ https_client::https_client(const std::string &hostname, uint16_t port, const st
content_length(0),
request_headers(extra_headers),
status(0),
http_protocol(protocol),
timeout(request_timeout)
{
nonblocking = false;
Expand All @@ -57,7 +58,7 @@ void https_client::connect()
}
if (this->sfd != SOCKET_ERROR) {
this->write(
this->request_type + " " + this->path + " HTTP/1.1\r\n"
this->request_type + " " + this->path + " HTTP/" + http_protocol + "\r\n"
"Host: " + this->hostname + "\r\n"
"pragma: no-cache\r\n"
"Connection: keep-alive\r\n"
Expand Down
14 changes: 7 additions & 7 deletions src/dpp/queues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

namespace dpp {

http_request::http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata, http_method _method, const std::string &audit_reason, const std::string &filename, const std::string &filecontent, const std::string &filemimetype)
: complete_handler(completion), completed(false), non_discord(false), endpoint(_endpoint), parameters(_parameters), postdata(_postdata), method(_method), reason(audit_reason), mimetype("application/json"), waiting(false)
http_request::http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata, http_method _method, const std::string &audit_reason, const std::string &filename, const std::string &filecontent, const std::string &filemimetype, const std::string &http_protocol)
: complete_handler(completion), completed(false), non_discord(false), endpoint(_endpoint), parameters(_parameters), postdata(_postdata), method(_method), reason(audit_reason), mimetype("application/json"), waiting(false), protocol(http_protocol)
{
if (!filename.empty()) {
file_name.push_back(filename);
Expand All @@ -46,14 +46,14 @@ http_request::http_request(const std::string &_endpoint, const std::string &_par
}
}

http_request::http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata, http_method method, const std::string &audit_reason, const std::vector<std::string> &filename, const std::vector<std::string> &filecontent, const std::vector<std::string> &filemimetypes)
: complete_handler(completion), completed(false), non_discord(false), endpoint(_endpoint), parameters(_parameters), postdata(_postdata), method(method), reason(audit_reason), file_name(filename), file_content(filecontent), file_mimetypes(filemimetypes), mimetype("application/json"), waiting(false)
http_request::http_request(const std::string &_endpoint, const std::string &_parameters, http_completion_event completion, const std::string &_postdata, http_method method, const std::string &audit_reason, const std::vector<std::string> &filename, const std::vector<std::string> &filecontent, const std::vector<std::string> &filemimetypes, const std::string &http_protocol)
: complete_handler(completion), completed(false), non_discord(false), endpoint(_endpoint), parameters(_parameters), postdata(_postdata), method(method), reason(audit_reason), file_name(filename), file_content(filecontent), file_mimetypes(filemimetypes), mimetype("application/json"), waiting(false), protocol(http_protocol)
{
}


http_request::http_request(const std::string &_url, http_completion_event completion, http_method _method, const std::string &_postdata, const std::string &_mimetype, const std::multimap<std::string, std::string> &_headers)
: complete_handler(completion), completed(false), non_discord(true), endpoint(_url), postdata(_postdata), method(_method), mimetype(_mimetype), req_headers(_headers), waiting(false)
http_request::http_request(const std::string &_url, http_completion_event completion, http_method _method, const std::string &_postdata, const std::string &_mimetype, const std::multimap<std::string, std::string> &_headers, const std::string &http_protocol)
: complete_handler(completion), completed(false), non_discord(true), endpoint(_url), postdata(_postdata), method(_method), mimetype(_mimetype), req_headers(_headers), waiting(false), protocol(http_protocol)
{
}

Expand Down Expand Up @@ -176,7 +176,7 @@ http_request_completion_t http_request::run(cluster* owner) {
}
http_connect_info hci = https_client::get_host_info(_host);
try {
https_client cli(hci.hostname, hci.port, _url, request_verb[method], multipart.body, headers, !hci.is_ssl);
https_client cli(hci.hostname, hci.port, _url, request_verb[method], multipart.body, headers, !hci.is_ssl, 5, protocol);
rv.latency = dpp::utility::time_f() - start;
if (cli.get_status() < 100) {
rv.error = h_connection;
Expand Down
Loading