Skip to content

Commit

Permalink
fix: large https request body could not be sent
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis committed Dec 18, 2024
1 parent d821e72 commit 40a2546
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# TODO: Discuss about -readability-identifier-length, -readability-avoid-const-params-in-decls
Checks: "-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,llvm-namespace-comment,modernize-*,performance-*,portability-*,readability-*,-bugprone-implicit-widening-of-multiplication-result,-bugprone-easily-swappable-parameters,-readability-identifier-length,-portability-restrict-system-includes,-modernize-use-trailing-return-type,-cppcoreguidelines-non-private-member-variables-in-classes,-readability-avoid-const-params-in-decls,-cppcoreguidelines-owning-memory,-readability-function-cognitive-complexity,-cppcoreguidelines-avoid-do-while"
Checks: "-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,llvm-namespace-comment,modernize-*,performance-*,portability-*,readability-*,-bugprone-implicit-widening-of-multiplication-result,-bugprone-easily-swappable-parameters,-readability-identifier-length,-portability-restrict-system-includes,-modernize-use-trailing-return-type,-cppcoreguidelines-non-private-member-variables-in-classes,-readability-avoid-const-params-in-decls,-cppcoreguidelines-owning-memory,-readability-function-cognitive-complexity,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay"
28 changes: 28 additions & 0 deletions include/dpp/sslclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class DPP_EXPORT ssl_client
*/
std::mutex ssl_mutex;

/**
* @brief Mutex for output buffer
*/
std::mutex out_mutex;

/**
* @brief Start offset into internal ring buffer for client to server IO
*/
Expand Down Expand Up @@ -217,7 +222,30 @@ class DPP_EXPORT ssl_client
*/
virtual void connect();

/**
* @brief Set this to true to log all IO to debug for this connection.
* This is an internal developer facility. Do not enable it unless you
* need to, as it will be very noisy.
*/
bool raw_trace{false};

/**
* @brief If raw_trace is set to true, log a debug message for this connection
* @param message debug message
*/
void do_raw_trace(const std::string& message) const;

public:
/**
* @brief For low-level debugging, calling this function will
* enable low level I/O logging for this connection to the logger.
* This can be very loud, and output a lot of data, so only enable it
* selectively where you need it.
*
* Generally, you won't need this, it is a library development utility.
*/
void enable_raw_tracing();

/**
* @brief Get the bytes out objectGet total bytes sent
* @return uint64_t bytes sent
Expand Down
63 changes: 33 additions & 30 deletions src/dpp/httpsclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <climits>
#include <dpp/httpsclient.h>
#include <dpp/utility.h>
#include <dpp/cluster.h>

namespace dpp {

Expand Down Expand Up @@ -54,6 +55,7 @@ void https_client::connect()
for (auto& [k,v] : request_headers) {
map_headers += k + ": " + v + "\r\n";
}

if (this->sfd != SOCKET_ERROR) {
this->socket_write(
this->request_type + " " + this->path + " HTTP/" + http_protocol + "\r\n"
Expand All @@ -72,43 +74,44 @@ void https_client::connect()
}

multipart_content https_client::build_multipart(const std::string &json, const std::vector<std::string>& filenames, const std::vector<std::string>& contents, const std::vector<std::string>& mimetypes) {

if (filenames.empty() && contents.empty()) {
/* If there are no files to upload, there is no need to build a multipart body */
if (!json.empty()) {
return { json, "application/json" };
} else {
return {json, ""};
}
} else {
/* Note: loss of upper 32 bits on this value is INTENTIONAL */
uint32_t dummy1 = (uint32_t)time(nullptr) + (uint32_t)time(nullptr);
time_t dummy2 = time(nullptr) * time(nullptr);
const std::string two_cr("\r\n\r\n");
const std::string boundary("-------------" + to_hex(dummy1) + to_hex(dummy2));
const std::string part_start("--" + boundary + "\r\nContent-Disposition: form-data; ");
const std::string mime_type_start("\r\nContent-Type: ");
const std::string default_mime_type("application/octet-stream");

std::string content("--" + boundary);
return {json, ""};
}

/* Special case, single file */
content += "\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name=\"payload_json\"" + two_cr;
content += json + "\r\n";
if (filenames.size() == 1 && contents.size() == 1) {
content += part_start + "name=\"file\"; filename=\"" + filenames[0] + "\"";
content += mime_type_start + (mimetypes.empty() || mimetypes[0].empty() ? default_mime_type : mimetypes[0]) + two_cr;
content += contents[0];
} else {
/* Multiple files */
for (size_t i = 0; i < filenames.size(); ++i) {
content += part_start + "name=\"files[" + std::to_string(i) + "]\"; filename=\"" + filenames[i] + "\"";
content += "\r\nContent-Type: " + (mimetypes.size() <= i || mimetypes[i].empty() ? default_mime_type : mimetypes[i]) + two_cr;
content += contents[i];
content += "\r\n";
}
/* Note: loss of upper 32 bits on this value is INTENTIONAL */
uint32_t dummy1 = (uint32_t)time(nullptr) + (uint32_t)time(nullptr);
time_t dummy2 = time(nullptr) * time(nullptr);
const std::string two_cr("\r\n\r\n");
const std::string boundary("-------------" + to_hex(dummy1) + to_hex(dummy2));
const std::string part_start("--" + boundary + "\r\nContent-Disposition: form-data; ");
const std::string mime_type_start("\r\nContent-Type: ");
const std::string default_mime_type("application/octet-stream");

std::string content("--" + boundary);

/* Special case, single file */
content += "\r\nContent-Type: application/json\r\nContent-Disposition: form-data; name=\"payload_json\"" + two_cr;
content += json + "\r\n";
if (filenames.size() == 1 && contents.size() == 1) {
content += part_start + "name=\"file\"; filename=\"" + filenames[0] + "\"";
content += mime_type_start + (mimetypes.empty() || mimetypes[0].empty() ? default_mime_type : mimetypes[0]) + two_cr;
content += contents[0];
} else {
/* Multiple files */
for (size_t i = 0; i < filenames.size(); ++i) {
content += part_start + "name=\"files[" + std::to_string(i) + "]\"; filename=\"" + filenames[i] + "\"";
content += "\r\nContent-Type: " + (mimetypes.size() <= i || mimetypes[i].empty() ? default_mime_type : mimetypes[i]) + two_cr;
content += contents[i];
content += "\r\n";
}
content += "\r\n--" + boundary + "--";
return { content, "multipart/form-data; boundary=" + boundary };
}
content += "\r\n--" + boundary + "--";
return { content, "multipart/form-data; boundary=" + boundary };
}

const std::string https_client::get_header(std::string header_name) const {
Expand Down
Loading

0 comments on commit 40a2546

Please sign in to comment.