handle text frames properly, add docs

This commit is contained in:
ading2210 2024-01-26 20:27:15 -05:00
parent b053ec8e77
commit 9cc0e4178b
6 changed files with 67 additions and 19 deletions

View file

@ -7,6 +7,7 @@ This is an experimental port of [libcurl](https://curl.se/libcurl/) to WebAssemb
- End to end encryption between the browser and the destination server
- Support for up to TLS 1.3
- Support for tunneling HTTP/2 connections
- Support for proxying WebSockets
- Bypass CORS restrictions
- Low latency via multiplexing and reusing open connections
@ -54,6 +55,21 @@ Most of the standard Fetch API's features are supported, with the exception of:
- Sending credentials/cookies automatically
- Caching
### Creating WebSocket Connections:
To use WebSockets, create a `libcurl.WebSocket` object, which works identically to the regular [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object.
```js
let ws = new libcurl.WebSocket("wss://echo.websocket.org");
ws.binaryType = "arraybuffer";
ws.addEventListener("open", () => {
console.log("ws connected!");
ws.send("hello".repeat(128));
});
ws.addEventListener("message", (event) => {
let text = new TextDecoder().decode(event.data);
console.log(text);
});
```
### Changing the Websocket URL:
You can change the URL of the websocket proxy by using `libcurl.set_websocket`.
```js

View file

@ -11,6 +11,7 @@ get_result_size
get_result_buffer
get_result_code
get_result_closed
get_result_fragment
get_result_bytes_left
get_result_is_text
free

View file

@ -13,6 +13,7 @@ struct WSResult {
int res;
int buffer_size;
int closed;
int fragment;
int bytes_left;
int is_text;
char* buffer;
};

View file

@ -18,13 +18,16 @@ struct WSResult* recv_from_websocket(CURL* http_handle, int buffer_size) {
result->buffer = buffer;
result->res = (int) res;
result->closed = (ws_meta->flags & CURLWS_CLOSE);
result->fragment = ws_meta->bytesleft;
result->is_text = (ws_meta->flags & CURLWS_TEXT);
result->bytes_left = ws_meta->bytesleft;
return result;
}
int send_to_websocket(CURL* http_handle, const char* data, int data_len) {
int send_to_websocket(CURL* http_handle, const char* data, int data_len, int is_text) {
size_t sent;
CURLcode res = curl_ws_send(http_handle, data, data_len, &sent, 0, CURLWS_BINARY);
unsigned int flags = CURLWS_BINARY;
if (is_text) flags = CURLWS_TEXT;
CURLcode res = curl_ws_send(http_handle, data, data_len, &sent, 0, flags);
return (int) res;
}
@ -55,6 +58,9 @@ int get_result_code (const struct WSResult* result) {
int get_result_closed (const struct WSResult* result) {
return result->closed;
}
int get_result_fragment (const struct WSResult* result) {
return result->fragment;
int get_result_bytes_left (const struct WSResult* result) {
return result->bytes_left;
}
int get_result_is_text (const struct WSResult* result) {
return result->is_text;
}

View file

@ -55,10 +55,11 @@ class CurlWebSocket extends EventTarget {
_free(data_ptr);
this.recv_buffer.push(data);
if (data_size !== buffer_size && !_get_result_fragment(result_ptr)) { //message finished
if (data_size !== buffer_size && !_get_result_bytes_left(result_ptr)) { //message finished
let full_data = merge_arrays(this.recv_buffer);
let is_text = _get_result_is_text(result_ptr)
this.recv_buffer = [];
this.recv_callback(full_data);
this.recv_callback(full_data, is_text);
}
}
@ -75,17 +76,25 @@ class CurlWebSocket extends EventTarget {
}, 1);
}
recv_callback(data) {
if (this.binaryType == "blob") {
data = new Blob(data);
}
else if (this.binaryType == "arraybuffer") {
data = data.buffer;
recv_callback(data, is_text=false) {
let converted;
if (is_text) {
converted = new TextDecoder().decode(data);
console.log(is_text);
}
else {
throw "invalid binaryType string";
if (this.binaryType == "blob") {
converted = new Blob(data);
}
else if (this.binaryType == "arraybuffer") {
converted = data.buffer;
}
else {
throw "invalid binaryType string";
}
}
let msg_event = new MessageEvent("message", {data: data});
let msg_event = new MessageEvent("message", {data: converted});
this.onmessage(msg_event);
this.dispatchEvent(msg_event);
}
@ -118,6 +127,7 @@ class CurlWebSocket extends EventTarget {
}
send(data) {
let is_text = false;
if (this.status === this.CONNECTING) {
throw new DOMException("ws not ready yet");
}
@ -128,6 +138,7 @@ class CurlWebSocket extends EventTarget {
let data_array;
if (typeof data === "string") {
data_array = new TextEncoder().encode(data);
is_text = true;
}
else if (data instanceof Blob) {
data.arrayBuffer().then(array_buffer => {
@ -157,11 +168,24 @@ class CurlWebSocket extends EventTarget {
let data_ptr = allocate_array(data_array);
let data_len = data.length;
_send_to_websocket(this.http_handle, data_ptr, data_len);
_send_to_websocket(this.http_handle, data_ptr, data_len, is_text);
_free(data_ptr);
}
close() {
_close_websocket(this.http_handle);
}
get readyState() {
return this.status;
}
get bufferedAmount() {
return 0;
}
get protocol() {
return "";
}
get extensions() {
return "";
}
}

@ -1 +1 @@
Subproject commit 0596aefa8206bbb128cab1f4b1ad4241289d2fda
Subproject commit 51ad95a6d912ec404c20284f0cded40c0b5c4e62