|
4 | 4 | #include "sentry_client_report.h" |
5 | 5 | #include "sentry_database.h" |
6 | 6 | #include "sentry_envelope.h" |
| 7 | +#include "sentry_json.h" |
7 | 8 | #include "sentry_options.h" |
8 | 9 | #include "sentry_ratelimiter.h" |
9 | 10 | #include "sentry_retry.h" |
|
20 | 21 |
|
21 | 22 | #define ENVELOPE_MIME "application/x-sentry-envelope" |
22 | 23 | #define TUS_MIME "application/offset+octet-stream" |
23 | | -#define TUS_MAX_HTTP_HEADERS 4 |
| 24 | +#define TUS_MAX_HTTP_HEADERS 5 |
24 | 25 | #ifdef SENTRY_TRANSPORT_COMPRESSION |
25 | 26 | # define MAX_HTTP_HEADERS 4 |
26 | 27 | #else |
@@ -195,9 +196,39 @@ sentry__prepared_http_request_free(sentry_prepared_http_request_t *req) |
195 | 196 | sentry_free(req); |
196 | 197 | } |
197 | 198 |
|
| 199 | +static char * |
| 200 | +tus_build_upload_metadata(const char *attachment_type) |
| 201 | +{ |
| 202 | + sentry_jsonwriter_t *jw = sentry__jsonwriter_new_sb(NULL); |
| 203 | + sentry__jsonwriter_write_object_start(jw); |
| 204 | + sentry__jsonwriter_write_key(jw, "attachment_type"); |
| 205 | + sentry__jsonwriter_write_str(jw, attachment_type); |
| 206 | + sentry__jsonwriter_write_object_end(jw); |
| 207 | + |
| 208 | + size_t json_len; |
| 209 | + char *json = sentry__jsonwriter_into_string(jw, &json_len); |
| 210 | + if (!json) { |
| 211 | + return NULL; |
| 212 | + } |
| 213 | + |
| 214 | + char *encoded = sentry__base64_encode(json, json_len); |
| 215 | + sentry_free(json); |
| 216 | + if (!encoded) { |
| 217 | + return NULL; |
| 218 | + } |
| 219 | + |
| 220 | + sentry_stringbuilder_t sb; |
| 221 | + sentry__stringbuilder_init(&sb); |
| 222 | + sentry__stringbuilder_append(&sb, "sentry "); |
| 223 | + sentry__stringbuilder_append(&sb, encoded); |
| 224 | + sentry_free(encoded); |
| 225 | + |
| 226 | + return sentry__stringbuilder_into_string(&sb); |
| 227 | +} |
| 228 | + |
198 | 229 | static sentry_prepared_http_request_t * |
199 | | -prepare_tus_request_common( |
200 | | - size_t upload_size, const sentry_dsn_t *dsn, const char *user_agent) |
| 230 | +prepare_tus_request_common(size_t upload_size, const char *attachment_type, |
| 231 | + const sentry_dsn_t *dsn, const char *user_agent) |
201 | 232 | { |
202 | 233 | if (!dsn || !dsn->is_valid) { |
203 | 234 | return NULL; |
@@ -234,12 +265,19 @@ prepare_tus_request_common( |
234 | 265 | h->key = "upload-length"; |
235 | 266 | h->value = sentry__uint64_to_string((uint64_t)upload_size); |
236 | 267 |
|
| 268 | + if (!sentry__string_empty(attachment_type)) { |
| 269 | + h = &req->headers[req->headers_len++]; |
| 270 | + h->key = "upload-metadata"; |
| 271 | + h->value = tus_build_upload_metadata(attachment_type); |
| 272 | + } |
| 273 | + |
237 | 274 | return req; |
238 | 275 | } |
239 | 276 |
|
240 | 277 | static sentry_prepared_http_request_t * |
241 | 278 | prepare_tus_upload_request(const char *location, const sentry_path_t *path, |
242 | | - size_t file_size, const sentry_dsn_t *dsn, const char *user_agent) |
| 279 | + size_t file_size, const char *attachment_type, const sentry_dsn_t *dsn, |
| 280 | + const char *user_agent) |
243 | 281 | { |
244 | 282 | if (!location || !path) { |
245 | 283 | return NULL; |
@@ -282,6 +320,12 @@ prepare_tus_upload_request(const char *location, const sentry_path_t *path, |
282 | 320 | h->key = "upload-offset"; |
283 | 321 | h->value = sentry__string_clone("0"); |
284 | 322 |
|
| 323 | + if (!sentry__string_empty(attachment_type)) { |
| 324 | + h = &req->headers[req->headers_len++]; |
| 325 | + h->key = "upload-metadata"; |
| 326 | + h->value = tus_build_upload_metadata(attachment_type); |
| 327 | + } |
| 328 | + |
285 | 329 | return req; |
286 | 330 | } |
287 | 331 |
|
@@ -346,22 +390,22 @@ http_update_ratelimiter( |
346 | 390 | // resulting remote location URL (caller frees) in `location_out`. |
347 | 391 | static int |
348 | 392 | tus_upload_file(http_transport_state_t *state, const sentry_path_t *cache_path, |
349 | | - const char *basename, char **location_out) |
| 393 | + const sentry_attachment_ref_t *ref, char **location_out) |
350 | 394 | { |
351 | | - if (!basename || *basename == '\0') { |
| 395 | + if (sentry__string_empty(ref->path)) { |
352 | 396 | return RESULT_ERROR; |
353 | 397 | } |
354 | 398 | *location_out = NULL; |
355 | | - sentry_path_t *att_file = sentry__path_join_str(cache_path, basename); |
| 399 | + sentry_path_t *att_file = sentry__path_join_str(cache_path, ref->path); |
356 | 400 | size_t file_size = att_file ? sentry__path_get_size(att_file) : 0; |
357 | 401 | if (!att_file || file_size == 0) { |
358 | 402 | sentry__path_free(att_file); |
359 | 403 | return RESULT_ERROR; |
360 | 404 | } |
361 | 405 |
|
362 | 406 | // Step 1: TUS creation (POST, no body) |
363 | | - sentry_prepared_http_request_t *req |
364 | | - = prepare_tus_request_common(file_size, state->dsn, state->user_agent); |
| 407 | + sentry_prepared_http_request_t *req = prepare_tus_request_common( |
| 408 | + file_size, ref->attachment_type, state->dsn, state->user_agent); |
365 | 409 | if (!req) { |
366 | 410 | sentry__path_free(att_file); |
367 | 411 | return RESULT_ERROR; |
@@ -393,8 +437,8 @@ tus_upload_file(http_transport_state_t *state, const sentry_path_t *cache_path, |
393 | 437 | sentry__path_free(att_file); |
394 | 438 | return RESULT_ERROR; |
395 | 439 | } |
396 | | - req = prepare_tus_upload_request( |
397 | | - patch_url, att_file, file_size, state->dsn, state->user_agent); |
| 440 | + req = prepare_tus_upload_request(patch_url, att_file, file_size, |
| 441 | + ref->attachment_type, state->dsn, state->user_agent); |
398 | 442 | sentry_free(patch_url); |
399 | 443 | sentry__path_free(att_file); |
400 | 444 | if (!req) { |
@@ -553,8 +597,7 @@ resolve_attachment_refs( |
553 | 597 | } |
554 | 598 |
|
555 | 599 | char *new_location = NULL; |
556 | | - int result |
557 | | - = tus_upload_file(state, cache_path, ref.path, &new_location); |
| 600 | + int result = tus_upload_file(state, cache_path, &ref, &new_location); |
558 | 601 | if (new_location) { |
559 | 602 | bool resolved = sentry__envelope_item_resolve_attachment_ref( |
560 | 603 | item, new_location); |
@@ -933,17 +976,19 @@ sentry__http_transport_get_bgworker(sentry_transport_t *transport) |
933 | 976 | #endif |
934 | 977 |
|
935 | 978 | sentry_prepared_http_request_t * |
936 | | -sentry__prepare_tus_create_request( |
937 | | - size_t file_size, const sentry_dsn_t *dsn, const char *user_agent) |
| 979 | +sentry__prepare_tus_create_request(size_t file_size, |
| 980 | + const char *attachment_type, const sentry_dsn_t *dsn, |
| 981 | + const char *user_agent) |
938 | 982 | { |
939 | | - return prepare_tus_request_common(file_size, dsn, user_agent); |
| 983 | + return prepare_tus_request_common( |
| 984 | + file_size, attachment_type, dsn, user_agent); |
940 | 985 | } |
941 | 986 |
|
942 | 987 | sentry_prepared_http_request_t * |
943 | 988 | sentry__prepare_tus_upload_request(const char *location, |
944 | | - const sentry_path_t *path, size_t file_size, const sentry_dsn_t *dsn, |
945 | | - const char *user_agent) |
| 989 | + const sentry_path_t *path, size_t file_size, const char *attachment_type, |
| 990 | + const sentry_dsn_t *dsn, const char *user_agent) |
946 | 991 | { |
947 | 992 | return prepare_tus_upload_request( |
948 | | - location, path, file_size, dsn, user_agent); |
| 993 | + location, path, file_size, attachment_type, dsn, user_agent); |
949 | 994 | } |
0 commit comments