Skip to content

Commit d1ee548

Browse files
committed
ref(transport): unify and restructure HTTP transport layer (#1514)
1 parent 616b4d2 commit d1ee548

11 files changed

Lines changed: 1024 additions & 980 deletions

src/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ sentry_target_sources_cwd(sentry
6464
transports/sentry_disk_transport.c
6565
transports/sentry_disk_transport.h
6666
transports/sentry_function_transport.c
67+
transports/sentry_http_transport.c
68+
transports/sentry_http_transport.h
6769
unwinder/sentry_unwinder.c
6870
)
6971

@@ -119,11 +121,11 @@ endif()
119121
# transport
120122
if(SENTRY_TRANSPORT_CURL)
121123
sentry_target_sources_cwd(sentry
122-
transports/sentry_transport_curl.c
124+
transports/sentry_http_transport_curl.c
123125
)
124126
elseif(SENTRY_TRANSPORT_WINHTTP)
125127
sentry_target_sources_cwd(sentry
126-
transports/sentry_transport_winhttp.c
128+
transports/sentry_http_transport_winhttp.c
127129
)
128130
elseif(SENTRY_TRANSPORT_NONE)
129131
sentry_target_sources_cwd(sentry

src/sentry_transport.c

Lines changed: 1 addition & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,6 @@
22
#include "sentry_alloc.h"
33
#include "sentry_envelope.h"
44
#include "sentry_options.h"
5-
#include "sentry_ratelimiter.h"
6-
#include "sentry_string.h"
7-
8-
#ifdef SENTRY_TRANSPORT_COMPRESSION
9-
# include "zlib.h"
10-
#endif
11-
12-
#define ENVELOPE_MIME "application/x-sentry-envelope"
13-
#ifdef SENTRY_TRANSPORT_COMPRESSION
14-
// The headers we use are: `x-sentry-auth`, `content-type`, `content-encoding`,
15-
// `content-length`
16-
# define MAX_HTTP_HEADERS 4
17-
#else
18-
// The headers we use are: `x-sentry-auth`, `content-type`, `content-length`
19-
# define MAX_HTTP_HEADERS 3
20-
#endif
215

226
struct sentry_transport_s {
237
void (*send_envelope_func)(sentry_envelope_t *envelope, void *state);
@@ -158,162 +142,8 @@ sentry_transport_free(sentry_transport_t *transport)
158142
sentry_free(transport);
159143
}
160144

161-
#ifdef SENTRY_UNITTEST
162145
void *
163-
sentry__transport_get_bgworker(sentry_transport_t *transport)
146+
sentry__transport_get_state(sentry_transport_t *transport)
164147
{
165-
// For HTTP transports (curl/winhttp), the transport state is the bgworker
166148
return transport ? transport->state : NULL;
167149
}
168-
#endif
169-
170-
#ifdef SENTRY_TRANSPORT_COMPRESSION
171-
static bool
172-
gzipped_with_compression(const char *body, const size_t body_len,
173-
char **compressed_body, size_t *compressed_body_len)
174-
{
175-
if (!body || body_len == 0) {
176-
return false;
177-
}
178-
179-
z_stream stream;
180-
memset(&stream, 0, sizeof(stream));
181-
stream.next_in = (unsigned char *)body;
182-
stream.avail_in = (unsigned int)body_len;
183-
184-
int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
185-
MAX_WBITS + 16, 9, Z_DEFAULT_STRATEGY);
186-
if (err != Z_OK) {
187-
SENTRY_WARNF("deflateInit2 failed: %d", err);
188-
return false;
189-
}
190-
191-
size_t len = compressBound((unsigned long)body_len);
192-
char *buffer = sentry_malloc(len);
193-
if (!buffer) {
194-
deflateEnd(&stream);
195-
return false;
196-
}
197-
198-
while (err == Z_OK) {
199-
stream.next_out = (unsigned char *)(buffer + stream.total_out);
200-
stream.avail_out = (unsigned int)(len - stream.total_out);
201-
err = deflate(&stream, Z_FINISH);
202-
}
203-
204-
if (err != Z_STREAM_END) {
205-
SENTRY_WARNF("deflate failed: %d", err);
206-
sentry_free(buffer);
207-
buffer = NULL;
208-
deflateEnd(&stream);
209-
return false;
210-
}
211-
212-
*compressed_body_len = stream.total_out;
213-
*compressed_body = buffer;
214-
215-
deflateEnd(&stream);
216-
return true;
217-
}
218-
#endif
219-
220-
sentry_prepared_http_request_t *
221-
sentry__prepare_http_request(sentry_envelope_t *envelope,
222-
const sentry_dsn_t *dsn, const sentry_rate_limiter_t *rl,
223-
const char *user_agent)
224-
{
225-
if (!dsn || !dsn->is_valid) {
226-
return NULL;
227-
}
228-
229-
size_t body_len = 0;
230-
bool body_owned = true;
231-
char *body = sentry_envelope_serialize_ratelimited(
232-
envelope, rl, &body_len, &body_owned);
233-
if (!body) {
234-
return NULL;
235-
}
236-
237-
#ifdef SENTRY_TRANSPORT_COMPRESSION
238-
bool compressed = false;
239-
char *compressed_body = NULL;
240-
size_t compressed_body_len = 0;
241-
compressed = gzipped_with_compression(
242-
body, body_len, &compressed_body, &compressed_body_len);
243-
if (compressed) {
244-
if (body_owned) {
245-
sentry_free(body);
246-
body_owned = false;
247-
}
248-
body = compressed_body;
249-
body_len = compressed_body_len;
250-
body_owned = true;
251-
}
252-
#endif
253-
254-
sentry_prepared_http_request_t *req
255-
= SENTRY_MAKE(sentry_prepared_http_request_t);
256-
if (!req) {
257-
if (body_owned) {
258-
sentry_free(body);
259-
}
260-
return NULL;
261-
}
262-
req->headers = sentry_malloc(
263-
sizeof(sentry_prepared_http_header_t) * MAX_HTTP_HEADERS);
264-
if (!req->headers) {
265-
sentry_free(req);
266-
if (body_owned) {
267-
sentry_free(body);
268-
}
269-
return NULL;
270-
}
271-
req->headers_len = 0;
272-
273-
req->method = "POST";
274-
req->url = sentry__dsn_get_envelope_url(dsn);
275-
276-
sentry_prepared_http_header_t *h;
277-
h = &req->headers[req->headers_len++];
278-
h->key = "x-sentry-auth";
279-
h->value = sentry__dsn_get_auth_header(dsn, user_agent);
280-
281-
h = &req->headers[req->headers_len++];
282-
h->key = "content-type";
283-
h->value = sentry__string_clone(ENVELOPE_MIME);
284-
285-
#ifdef SENTRY_TRANSPORT_COMPRESSION
286-
if (compressed) {
287-
h = &req->headers[req->headers_len++];
288-
h->key = "content-encoding";
289-
h->value = sentry__string_clone("gzip");
290-
}
291-
#endif
292-
293-
h = &req->headers[req->headers_len++];
294-
h->key = "content-length";
295-
h->value = sentry__int64_to_string((int64_t)body_len);
296-
297-
req->body = body;
298-
req->body_len = body_len;
299-
req->body_owned = body_owned;
300-
301-
return req;
302-
}
303-
304-
void
305-
sentry__prepared_http_request_free(sentry_prepared_http_request_t *req)
306-
{
307-
if (!req) {
308-
return;
309-
}
310-
sentry_free(req->url);
311-
for (size_t i = 0; i < req->headers_len; i++) {
312-
sentry_free(req->headers[i].value);
313-
}
314-
sentry_free(req->headers);
315-
if (req->body_owned) {
316-
sentry_free(req->body);
317-
}
318-
sentry_free(req);
319-
}

src/sentry_transport.h

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include "sentry_boot.h"
55
#include "sentry_database.h"
6-
#include "sentry_ratelimiter.h"
76
#include "sentry_utils.h"
87

98
/**
@@ -56,44 +55,6 @@ sentry_transport_t *sentry__transport_new_default(void);
5655
size_t sentry__transport_dump_queue(
5756
sentry_transport_t *transport, sentry_run_t *run);
5857

59-
#ifdef SENTRY_UNITTEST
60-
/**
61-
* Test helper function to get the bgworker from a transport.
62-
* Only available in unit tests and only works for HTTP transports.
63-
*/
64-
void *sentry__transport_get_bgworker(sentry_transport_t *transport);
65-
#endif
66-
67-
typedef struct sentry_prepared_http_header_s {
68-
const char *key;
69-
char *value;
70-
} sentry_prepared_http_header_t;
71-
72-
/**
73-
* This represents a HTTP request, with method, url, headers and a body.
74-
*/
75-
typedef struct sentry_prepared_http_request_s {
76-
const char *method;
77-
char *url;
78-
sentry_prepared_http_header_t *headers;
79-
size_t headers_len;
80-
char *body;
81-
size_t body_len;
82-
bool body_owned;
83-
} sentry_prepared_http_request_t;
84-
85-
/**
86-
* Consumes the given envelope and transforms it into into a prepared http
87-
* request. This can return NULL when all the items in the envelope have been
88-
* rate limited.
89-
*/
90-
sentry_prepared_http_request_t *sentry__prepare_http_request(
91-
sentry_envelope_t *envelope, const sentry_dsn_t *dsn,
92-
const sentry_rate_limiter_t *rl, const char *user_agent);
93-
94-
/**
95-
* Free a previously allocated HTTP request.
96-
*/
97-
void sentry__prepared_http_request_free(sentry_prepared_http_request_t *req);
58+
void *sentry__transport_get_state(sentry_transport_t *transport);
9859

9960
#endif

0 commit comments

Comments
 (0)