add abort controller support

This commit is contained in:
ading2210 2024-03-10 10:24:42 -04:00
parent 954ce1f60b
commit b9b871b25a
5 changed files with 40 additions and 7 deletions

View file

@ -1,6 +1,9 @@
# Libcurl.js Changelog:
## v0.5.0 (3/8/24):
## v0.5.1 (3/10/24):
- Added support for aborting requests
## v0.5.0 (3/9/24):
- Added support for streaming HTTP responses via a readable stream
- Improve compatibility for older browsers
- Support for all types of fetch request bodies

View file

@ -94,11 +94,10 @@ console.log(await r.text());
Most of the standard Fetch API's features are supported, with the exception of:
- CORS enforcement
- `FormData` or `URLSearchParams` as the request body
- Sending credentials/cookies automatically
- Caching
The response may contain multiple HTTP headers with the same name, which the `Headers` object isn't able to properly represent. If this matters to you, use `response.raw_headers`, which is an array of key value pairs, instead of `response.headers`. There is support for streaming the response body using a `ReadableStream`.
The response may contain multiple HTTP headers with the same name, which the `Headers` object isn't able to properly represent. If this matters to you, use `response.raw_headers`, which is an array of key value pairs, instead of `response.headers`. There is support for streaming the response body using a `ReadableStream`, as well as canceling requests using an `AbortSignal`.
Also note that there is a hard limit of 50 active TCP connections due to emscripten limitations.

View file

@ -173,6 +173,25 @@ async function create_options(params) {
function perform_request_async(url, params, body) {
return new Promise((resolve, reject) => {
let stream_controller;
let http_handle;
let response_obj;
let aborted = false;
//handle abort signals
if (params.signal instanceof AbortSignal) {
params.signal.addEventListener("abort", () => {
if (aborted) return;
aborted = true;
_cleanup_handle(http_handle);
if (!response_obj) {
reject(new DOMException("The operation was aborted."));
}
else {
stream_controller.error("The operation was aborted.");
}
});
}
let stream = new ReadableStream({
start(controller) {
stream_controller = controller;
@ -180,10 +199,21 @@ function perform_request_async(url, params, body) {
});
function data_callback(new_data) {
try {
stream_controller.enqueue(new_data);
}
catch (e) {
//the readable stream has been closed elsewhere, so cancel the request
if (e instanceof TypeError) {
_cleanup_handle(http_handle);
}
else {
throw e;
}
}
}
function headers_callback(response_info) {
let response_obj = create_response(stream, response_info);
response_obj = create_response(stream, response_info);
resolve(response_obj);
}
function finish_callback(error) {
@ -196,7 +226,7 @@ function perform_request_async(url, params, body) {
stream_controller.close();
}
perform_request(url, params, data_callback, finish_callback, headers_callback, body);
http_handle = perform_request(url, params, data_callback, finish_callback, headers_callback, body);
});
}

View file

@ -1,6 +1,6 @@
{
"name": "libcurl.js",
"version": "0.5.0",
"version": "0.5.1",
"description": "An experimental port of libcurl to WebAssembly for use in the browser.",
"main": "libcurl.mjs",
"scripts": {

View file

@ -7,6 +7,7 @@
cp package.json out
cp ../README.md out
cp ../LICENSE out
cp ../CHANGELOG.md out
cd out
npm publish