MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

handle broader stream chunks and cancel abandoned bodies

+67 -27
+7 -3
docs/reports/src/view.tsx
··· 73 73 meta={{ 74 74 url: 'https://js.report', 75 75 title: 'js.report', 76 - description: 'Crash reports for JavaScript runtimes.', 76 + description: 'Crash reports for the Ant runtime.', 77 77 }} 78 78 > 79 79 <Logo /> ··· 103 103 <b>Privacy.</b> <ins>Crash report storage policy.</ins> 104 104 </p> 105 105 <div class="policy"> 106 - <p>js.report does not store IP addresses in its database.</p> 107 106 <p> 108 107 The database stores the crash report JSON submitted by Ant, plus server metadata needed to 109 - render, deduplicate, and expire reports. 108 + render, deduplicate, and expire reports. Crash report dumps are retained for 30 days, then 109 + deleted. 110 + </p> 111 + <p> 112 + Ant does not upload personal information. It also does not store IP addresses in its 113 + database. It uploads only the crash fields listed below. 110 114 </p> 111 115 <p> 112 116 <span class="label">Submitted report fields:</span>
+60 -24
src/modules/server.c
··· 22 22 23 23 #include "modules/assert.h" 24 24 #include "modules/abort.h" 25 + #include "modules/blob.h" 25 26 #include "modules/buffer.h" 26 27 #include "modules/headers.h" 27 28 #include "modules/request.h" ··· 343 344 } 344 345 345 346 static bool server_response_chunk(server_request_t *req, ant_value_t value, const uint8_t **out, size_t *len) { 346 - TypedArrayData *ta = buffer_get_typedarray_data(value); 347 + blob_data_t *blob = NULL; 347 348 348 349 if (vtype(value) == T_STR) { 349 350 *out = (const uint8_t *)js_getstr(req->server->js, value, len); ··· 351 352 return true; 352 353 } 353 354 354 - if (!ta || ta->type != TYPED_ARRAY_UINT8) return false; 355 - if (!ta->buffer || ta->buffer->is_detached) { 356 - *out = NULL; 357 - *len = 0; 355 + if (is_object_type(value) && blob_is_blob(req->server->js, value)) { 356 + blob = blob_get_data(value); 357 + *out = blob ? blob->data : NULL; 358 + *len = blob ? blob->size : 0; 358 359 return true; 359 360 } 360 361 361 - *out = ta->buffer->data + ta->byte_offset; 362 - *len = ta->byte_length; 363 - return true; 362 + return buffer_source_get_bytes(req->server->js, value, out, len); 363 + } 364 + 365 + static void server_cancel_response_body(server_request_t *req, const char *message) { 366 + ant_t *js = NULL; 367 + 368 + ant_value_t stream = 0; 369 + ant_value_t reason = 0; 370 + ant_value_t result = 0; 371 + 372 + if (!req || !req->server || !is_object_type(req->response_obj)) return; 373 + 374 + js = req->server->js; 375 + stream = js_get_slot(req->response_obj, SLOT_RESPONSE_BODY_STREAM); 376 + if (!rs_is_stream(stream)) return; 377 + 378 + reason = make_dom_exception( 379 + js, message ? message : "The response body was canceled", 380 + "AbortError" 381 + ); 382 + 383 + result = readable_stream_cancel(js, stream, reason); 384 + if (vtype(result) == T_PROMISE) promise_mark_handled(result); 364 385 } 365 386 366 387 static void server_start_stream_read(server_request_t *req); ··· 428 449 return true; 429 450 } 430 451 452 + static bool server_queue_final_chunk(server_request_t *req, server_write_action_t action) { 453 + ant_http1_buffer_t buf; 454 + char *out = NULL; 455 + size_t out_len = 0; 456 + 457 + if (!req || !req->conn || ant_conn_is_closing(req->conn)) return false; 458 + 459 + ant_http1_buffer_init(&buf); 460 + if (!ant_http1_write_final_chunk(&buf)) { 461 + ant_http1_buffer_free(&buf); 462 + ant_conn_close(req->conn); 463 + return false; 464 + } 465 + 466 + out = ant_http1_buffer_take(&buf, &out_len); 467 + return server_queue_write(req->conn, req, out, out_len, action); 468 + } 469 + 431 470 static void server_send_basic_response( 432 471 ant_conn_t *conn, int status, const char *status_text, 433 472 const char *content_type, const uint8_t *body, size_t body_len ··· 515 554 out = ant_http1_buffer_take(&buf, &out_len); 516 555 ant_conn_set_timeout_ms(req->conn, req->server->idle_timeout_ms); 517 556 557 + if (body_is_stream && head_only) server_cancel_response_body( 558 + req, "The response body was canceled for a HEAD request" 559 + ); 560 + 518 561 server_queue_write( 519 562 req->conn, 520 563 req, out, out_len, ··· 594 637 if (!req) return js_mkundef(); 595 638 596 639 req->response_read_promise = js_mkundef(); 597 - if (req->conn && !ant_conn_is_closing(req->conn)) ant_conn_close(req->conn); 640 + server_queue_final_chunk(req, SERVER_WRITE_CLOSE_CLIENT); 598 641 server_request_release(req); 599 642 600 643 return js_mkundef(); ··· 624 667 625 668 done = js_get(js, result, "done"); 626 669 if (done == js_true) { 627 - ant_http1_buffer_init(&buf); 628 - if (!ant_http1_write_final_chunk(&buf)) { 629 - ant_http1_buffer_free(&buf); 630 - ant_conn_close(req->conn); 631 - server_request_release(req); 632 - return js_mkundef(); 633 - } 634 - 635 - out = ant_http1_buffer_take(&buf, &out_len); 636 670 ant_conn_set_timeout_ms(req->conn, req->server->idle_timeout_ms); 637 - 638 - server_queue_write( 639 - req->conn, 640 - req, out, out_len, 641 - req->keep_alive ? SERVER_WRITE_KEEP_ALIVE : SERVER_WRITE_CLOSE_CLIENT 671 + server_queue_final_chunk( 672 + req, req->keep_alive 673 + ? SERVER_WRITE_KEEP_ALIVE 674 + : SERVER_WRITE_CLOSE_CLIENT 642 675 ); 643 676 644 677 server_request_release(req); ··· 647 680 648 681 value = js_get(js, result, "value"); 649 682 if (!server_response_chunk(req, value, &chunk, &chunk_len)) { 650 - ant_conn_close(req->conn); 683 + fprintf(stderr, "Response body stream chunk must be a string, Blob, ArrayBuffer, DataView, or TypedArray\n"); 684 + server_cancel_response_body(req, "Invalid response body chunk"); 685 + server_queue_final_chunk(req, SERVER_WRITE_CLOSE_CLIENT); 651 686 server_request_release(req); 652 687 return js_mkundef(); 653 688 } ··· 920 955 uv_close((uv_handle_t *)&cs->drain_timer, server_on_drain_timer_close); 921 956 if (cs->active_req) { 922 957 server_abort_request(cs->active_req, "Client disconnected"); 958 + server_cancel_response_body(cs->active_req, "Client disconnected"); 923 959 cs->active_req->conn = NULL; 924 960 cs->active_req = NULL; 925 961 server_request_release(&cs->request);