Skip to content

Commit a0e3698

Browse files
committed
add gzip compression
1 parent 2ae5de6 commit a0e3698

File tree

3 files changed

+106
-7
lines changed

3 files changed

+106
-7
lines changed

CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ endif()
5555

5656
option(SENTRY_PIC "Build sentry (and dependent) libraries as position independent libraries" ON)
5757

58+
option(SENTRY_TRANSPORT_COMPRESSION " Enable transport gzip compression" OFF)
59+
5860
option(SENTRY_BUILD_TESTS "Build sentry-native tests" "${SENTRY_MAIN_PROJECT}")
5961
option(SENTRY_BUILD_EXAMPLES "Build sentry-native example(s)" "${SENTRY_MAIN_PROJECT}")
6062

@@ -291,6 +293,14 @@ if(SENTRY_TRANSPORT_CURL)
291293
endif()
292294
endif()
293295

296+
if(SENTRY_TRANSPORT_COMPRESSION)
297+
if(NOT ZLIB_FOUND)
298+
find_package(ZLIB REQUIRED)
299+
endif()
300+
301+
target_link_libraries(sentry PRIVATE ZLIB::ZLIB)
302+
endif()
303+
294304
set_property(TARGET sentry PROPERTY C_VISIBILITY_PRESET hidden)
295305
if(MSVC)
296306
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
@@ -593,4 +603,4 @@ endif()
593603
if(SENTRY_BUILD_SHARED_LIBS)
594604
target_link_libraries(sentry PRIVATE
595605
"$<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:Android>>:-Wl,--build-id=sha1,--version-script=${PROJECT_SOURCE_DIR}/src/exports.map>")
596-
endif()
606+
endif()

src/sentry_transport.c

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
#include "sentry_ratelimiter.h"
66
#include "sentry_string.h"
77

8+
89
#define ENVELOPE_MIME "application/x-sentry-envelope"
9-
// The headers we use are: `x-sentry-auth`, `content-type`, `content-length`
10-
#define MAX_HTTP_HEADERS 3
10+
// The headers we use are: `x-sentry-auth`, `content-type`, `content-encoding`, `content-length`
11+
#define MAX_HTTP_HEADERS 4
1112

1213
typedef struct sentry_transport_s {
1314
void (*send_envelope_func)(sentry_envelope_t *envelope, void *state);
@@ -165,9 +166,24 @@ sentry__prepare_http_request(sentry_envelope_t *envelope,
165166
return NULL;
166167
}
167168

169+
char *compressed_body = NULL;
170+
size_t compressed_body_len = 0;
171+
bool compressed = sentry_gzipped_with_compression(
172+
body, body_len, &compressed_body, &compressed_body_len);
173+
if (compressed) {
174+
if (body_owned) {
175+
sentry_free(body);
176+
body = NULL;
177+
body_owned = false;
178+
}
179+
}
180+
168181
sentry_prepared_http_request_t *req
169182
= SENTRY_MAKE(sentry_prepared_http_request_t);
170183
if (!req) {
184+
if (compressed) {
185+
sentry_free(compressed_body);
186+
}
171187
if (body_owned) {
172188
sentry_free(body);
173189
}
@@ -177,6 +193,9 @@ sentry__prepare_http_request(sentry_envelope_t *envelope,
177193
sizeof(sentry_prepared_http_header_t) * MAX_HTTP_HEADERS);
178194
if (!req->headers) {
179195
sentry_free(req);
196+
if (compressed) {
197+
sentry_free(compressed_body);
198+
}
180199
if (body_owned) {
181200
sentry_free(body);
182201
}
@@ -196,13 +215,29 @@ sentry__prepare_http_request(sentry_envelope_t *envelope,
196215
h->key = "content-type";
197216
h->value = sentry__string_clone(ENVELOPE_MIME);
198217

218+
if (compressed) {
219+
h = &req->headers[req->headers_len++];
220+
h->key = "content-encoding";
221+
h->value = sentry__string_clone("gzip");
222+
}
223+
199224
h = &req->headers[req->headers_len++];
200225
h->key = "content-length";
201-
h->value = sentry__int64_to_string((int64_t)body_len);
226+
if (compressed) {
227+
h->value = sentry__int64_to_string((int64_t)compressed_body_len);
228+
} else {
229+
h->value = sentry__int64_to_string((int64_t)body_len);
230+
}
202231

203-
req->body = body;
204-
req->body_len = body_len;
205-
req->body_owned = body_owned;
232+
if (compressed) {
233+
req->body = compressed_body;
234+
req->body_len = compressed_body_len;
235+
req->body_owned = true;
236+
} else {
237+
req->body = body;
238+
req->body_len = body_len;
239+
req->body_owned = body_owned;
240+
}
206241

207242
return req;
208243
}
@@ -223,3 +258,51 @@ sentry__prepared_http_request_free(sentry_prepared_http_request_t *req)
223258
}
224259
sentry_free(req);
225260
}
261+
262+
bool
263+
sentry_gzipped_with_compression(const char *body, const size_t body_len,
264+
char **compressed_body, size_t *compressed_body_len)
265+
{
266+
if (!body || body_len == 0) {
267+
return false;
268+
}
269+
270+
z_stream stream;
271+
memset(&stream, 0, sizeof(stream));
272+
stream.next_in = body;
273+
stream.avail_in = body_len;
274+
275+
int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
276+
MAX_WBITS + 16, 9, Z_DEFAULT_STRATEGY);
277+
if (err != Z_OK) {
278+
SENTRY_TRACEF("deflateInit2 failed: %d", err);
279+
return false;
280+
}
281+
282+
size_t len = compressBound(body_len);
283+
char *buffer = sentry_malloc(len);
284+
if (!buffer) {
285+
deflateEnd(&stream);
286+
return false;
287+
}
288+
289+
while (err == Z_OK) {
290+
stream.next_out = buffer + stream.total_out;
291+
stream.avail_out = len - stream.total_out;
292+
err = deflate(&stream, Z_FINISH);
293+
}
294+
295+
if (err != Z_STREAM_END) {
296+
SENTRY_TRACEF("deflate failed: %d", err);
297+
sentry_free(buffer);
298+
buffer = NULL;
299+
deflateEnd(&stream);
300+
return false;
301+
}
302+
303+
*compressed_body_len = stream.total_out;
304+
*compressed_body = buffer;
305+
306+
deflateEnd(&stream);
307+
return true;
308+
}

src/sentry_transport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,10 @@ sentry_prepared_http_request_t *sentry__prepare_http_request(
8989
*/
9090
void sentry__prepared_http_request_free(sentry_prepared_http_request_t *req);
9191

92+
/**
93+
* Gzip
94+
*/
95+
bool sentry_gzipped_with_compression(const char *body, const size_t body_len,
96+
char **compressed_body, size_t *compressed_body_len);
97+
9298
#endif

0 commit comments

Comments
 (0)