(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 1b11ef006a
commit a0d5f37402
14 changed files with 305 additions and 33 deletions

View File

@ -19,7 +19,7 @@ add_library(ixsentry STATIC
set(IXSENTRY_INCLUDE_DIRS
.
..
../third_party
../third_party/spdlog/include)
../ixcore
../third_party)
target_include_directories( ixsentry PUBLIC ${IXSENTRY_INCLUDE_DIRS} )

View File

@ -8,8 +8,9 @@
#include <chrono>
#include <iostream>
#include <fstream>
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
#include <spdlog/spdlog.h>
#include <ixcore/utils/IXCoreLogger.h>
namespace ix
@ -18,6 +19,7 @@ namespace ix
: _dsn(dsn)
, _validDsn(false)
, _luaFrameRegex("\t([^/]+):([0-9]+): in function ['<]([^/]+)['>]")
, _httpClient(std::make_shared<HttpClient>(true))
{
const std::regex dsnRegex("(http[s]?)://([^:]+):([^@]+)@([^/]+)/([0-9]+)");
std::smatch group;
@ -169,39 +171,64 @@ namespace ix
std::pair<HttpResponsePtr, std::string> SentryClient::send(const Json::Value& msg, bool verbose)
{
auto args = _httpClient.createRequest();
auto args = _httpClient->createRequest();
args->extraHeaders["X-Sentry-Auth"] = SentryClient::computeAuthHeader();
args->connectTimeout = 60;
args->transferTimeout = 5 * 60;
args->followRedirects = true;
args->verbose = verbose;
args->logger = [](const std::string& msg) { spdlog::info("request logger: {}", msg); };
args->logger = [](const std::string& msg) { ix::IXCoreLogger::Log(msg.c_str()); };
std::string body = computePayload(msg);
HttpResponsePtr response = _httpClient.post(_url, body, args);
if (verbose)
{
for (auto it : response->headers)
{
spdlog::info("{}: {}", it.first, it.second);
}
spdlog::info("Upload size: {}", response->uploadSize);
spdlog::info("Download size: {}", response->downloadSize);
spdlog::info("Status: {}", response->statusCode);
if (response->errorCode != HttpErrorCode::Ok)
{
spdlog::info("error message: {}", response->errorMsg);
}
if (response->headers["Content-Type"] != "application/octet-stream")
{
spdlog::info("payload: {}", response->payload);
}
}
HttpResponsePtr response = _httpClient->post(_url, body, args);
return std::make_pair(response, body);
}
// https://sentry.io/api/12345/minidump?sentry_key=abcdefgh");
std::string SentryClient::computeUrl(const std::string& project, const std::string& key)
{
std::stringstream ss;
ss << "https://sentry.io/api/"
<< project
<< "/minidump?sentry_key="
<< key;
return ss.str();
}
//
// curl -v -X POST -F upload_file_minidump=@ws/crash.dmp 'https://sentry.io/api/123456/minidump?sentry_key=12344567890'
//
void SentryClient::uploadMinidump(
const std::string& sentryMetadata,
const std::string& minidumpBytes,
const std::string& project,
const std::string& key,
bool verbose,
const OnResponseCallback& onResponseCallback)
{
std::string multipartBoundary = _httpClient->generateMultipartBoundary();
auto args = _httpClient->createRequest();
args->verb = HttpClient::kPost;
args->connectTimeout = 60;
args->transferTimeout = 5 * 60;
args->followRedirects = true;
args->verbose = verbose;
args->multipartBoundary = multipartBoundary;
args->logger = [](const std::string& msg) { ix::IXCoreLogger::Log(msg.c_str()); };
HttpFormDataParameters httpFormDataParameters;
httpFormDataParameters["upload_file_minidump"] = minidumpBytes;
HttpParameters httpParameters;
httpParameters["sentry"] = sentryMetadata;
args->url = computeUrl(project, key);
args->body = _httpClient->serializeHttpFormDataParameters(multipartBoundary, httpFormDataParameters, httpParameters);
_httpClient->performRequest(args, onResponseCallback);
}
} // namespace ix

View File

@ -10,6 +10,7 @@
#include <ixwebsocket/IXHttpClient.h>
#include <jsoncpp/json/json.h>
#include <regex>
#include <memory>
namespace ix
{
@ -23,12 +24,24 @@ namespace ix
Json::Value parseLuaStackTrace(const std::string& stack);
void uploadMinidump(
const std::string& sentryMetadata,
const std::string& minidumpBytes,
const std::string& project,
const std::string& key,
bool verbose,
const OnResponseCallback& onResponseCallback);
private:
int64_t getTimestamp();
std::string computeAuthHeader();
std::string getIso8601();
std::string computePayload(const Json::Value& msg);
std::string computeUrl(const std::string& project, const std::string& key);
void displayReponse(HttpResponsePtr response);
std::string _dsn;
bool _validDsn;
std::string _url;
@ -41,7 +54,7 @@ namespace ix
std::regex _luaFrameRegex;
HttpClient _httpClient;
std::shared_ptr<HttpClient> _httpClient;
};
} // namespace ix