(http client) Add support for multipart HTTP POST upload + (ixsentry) Add support for uploading a minidump to sentry

This commit is contained in:
Benjamin Sergeant
2019-11-25 21:08:43 -08:00
parent 69aa3839bf
commit 6054dd4b49
14 changed files with 305 additions and 33 deletions

View File

@ -66,6 +66,7 @@ namespace ix
using HttpResponsePtr = std::shared_ptr<HttpResponse>;
using HttpParameters = std::map<std::string, std::string>;
using HttpFormDataParameters = std::map<std::string, std::string>;
using Logger = std::function<void(const std::string&)>;
using OnResponseCallback = std::function<void(const HttpResponsePtr&)>;
@ -75,6 +76,7 @@ namespace ix
std::string verb;
WebSocketHttpHeaders extraHeaders;
std::string body;
std::string multipartBoundary;
int connectTimeout;
int transferTimeout;
bool followRedirects;

View File

@ -13,6 +13,7 @@
#include <assert.h>
#include <cstring>
#include <iomanip>
#include <random>
#include <sstream>
#include <vector>
#include <zlib.h>
@ -198,8 +199,16 @@ namespace ix
// Set default Content-Type if unspecified
if (args->extraHeaders.find("Content-Type") == args->extraHeaders.end())
{
ss << "Content-Type: application/x-www-form-urlencoded"
<< "\r\n";
if (args->multipartBoundary.empty())
{
ss << "Content-Type: application/x-www-form-urlencoded"
<< "\r\n";
}
else
{
ss << "Content-Type: multipart/form-data; boundary=" << args->multipartBoundary
<< "\r\n";
}
}
ss << "\r\n";
ss << body;
@ -597,6 +606,53 @@ namespace ix
return ss.str();
}
std::string HttpClient::serializeHttpFormDataParameters(
const std::string& multipartBoundary,
const HttpFormDataParameters& httpFormDataParameters,
const HttpParameters& httpParameters)
{
//
// --AaB03x
// Content-Disposition: form-data; name="submit-name"
// Larry
// --AaB03x
// Content-Disposition: form-data; name="foo.txt"; filename="file1.txt"
// Content-Type: text/plain
// ... contents of file1.txt ...
// --AaB03x--
//
std::stringstream ss;
for (auto&& it : httpFormDataParameters)
{
ss << "--" << multipartBoundary << "\r\n"
<< "Content-Disposition:"
<< " form-data; name=\"" << it.first << "\";"
<< " filename=\"" << it.first << "\""
<< "\r\n"
<< "Content-Type: application/octet-stream"
<< "\r\n"
<< "\r\n"
<< it.second << "\r\n";
}
for (auto&& it : httpParameters)
{
ss << "--" << multipartBoundary << "\r\n"
<< "Content-Disposition:"
<< " form-data; name=\"" << it.first << "\";"
<< "\r\n"
<< "\r\n"
<< it.second << "\r\n";
}
ss << "--" << multipartBoundary << "\r\n";
return ss.str();
}
bool HttpClient::gzipInflate(const std::string& in, std::string& out)
{
z_stream inflateState;
@ -649,4 +705,16 @@ namespace ix
args->logger(msg);
}
}
std::string HttpClient::generateMultipartBoundary()
{
std::string str("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
static std::random_device rd;
static std::mt19937 generator(rd());
std::shuffle(str.begin(), str.end(), generator);
return str;
}
} // namespace ix

View File

@ -64,6 +64,13 @@ namespace ix
std::string serializeHttpParameters(const HttpParameters& httpParameters);
std::string serializeHttpFormDataParameters(
const std::string& multipartBoundary,
const HttpFormDataParameters& httpFormDataParameters,
const HttpParameters& httpParameters = HttpParameters());
std::string generateMultipartBoundary();
std::string urlEncode(const std::string& value);
const static std::string kPost;

View File

@ -6,4 +6,4 @@
#pragma once
#define IX_WEBSOCKET_VERSION "7.3.5"
#define IX_WEBSOCKET_VERSION "7.4.0"