mirror of
https://github.com/ading2210/libcurl.js.git
synced 2025-05-12 14:00:01 -04:00
handle text frames properly, add docs
This commit is contained in:
parent
b053ec8e77
commit
9cc0e4178b
6 changed files with 67 additions and 19 deletions
16
README.md
16
README.md
|
@ -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
|
- End to end encryption between the browser and the destination server
|
||||||
- Support for up to TLS 1.3
|
- Support for up to TLS 1.3
|
||||||
- Support for tunneling HTTP/2 connections
|
- Support for tunneling HTTP/2 connections
|
||||||
|
- Support for proxying WebSockets
|
||||||
- Bypass CORS restrictions
|
- Bypass CORS restrictions
|
||||||
- Low latency via multiplexing and reusing open connections
|
- 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
|
- Sending credentials/cookies automatically
|
||||||
- Caching
|
- 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:
|
### Changing the Websocket URL:
|
||||||
You can change the URL of the websocket proxy by using `libcurl.set_websocket`.
|
You can change the URL of the websocket proxy by using `libcurl.set_websocket`.
|
||||||
```js
|
```js
|
||||||
|
|
|
@ -11,6 +11,7 @@ get_result_size
|
||||||
get_result_buffer
|
get_result_buffer
|
||||||
get_result_code
|
get_result_code
|
||||||
get_result_closed
|
get_result_closed
|
||||||
get_result_fragment
|
get_result_bytes_left
|
||||||
|
get_result_is_text
|
||||||
|
|
||||||
free
|
free
|
|
@ -13,6 +13,7 @@ struct WSResult {
|
||||||
int res;
|
int res;
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
int closed;
|
int closed;
|
||||||
int fragment;
|
int bytes_left;
|
||||||
|
int is_text;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
};
|
};
|
|
@ -18,13 +18,16 @@ struct WSResult* recv_from_websocket(CURL* http_handle, int buffer_size) {
|
||||||
result->buffer = buffer;
|
result->buffer = buffer;
|
||||||
result->res = (int) res;
|
result->res = (int) res;
|
||||||
result->closed = (ws_meta->flags & CURLWS_CLOSE);
|
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;
|
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;
|
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;
|
return (int) res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +58,9 @@ int get_result_code (const struct WSResult* result) {
|
||||||
int get_result_closed (const struct WSResult* result) {
|
int get_result_closed (const struct WSResult* result) {
|
||||||
return result->closed;
|
return result->closed;
|
||||||
}
|
}
|
||||||
int get_result_fragment (const struct WSResult* result) {
|
int get_result_bytes_left (const struct WSResult* result) {
|
||||||
return result->fragment;
|
return result->bytes_left;
|
||||||
|
}
|
||||||
|
int get_result_is_text (const struct WSResult* result) {
|
||||||
|
return result->is_text;
|
||||||
}
|
}
|
|
@ -55,10 +55,11 @@ class CurlWebSocket extends EventTarget {
|
||||||
_free(data_ptr);
|
_free(data_ptr);
|
||||||
|
|
||||||
this.recv_buffer.push(data);
|
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 full_data = merge_arrays(this.recv_buffer);
|
||||||
|
let is_text = _get_result_is_text(result_ptr)
|
||||||
this.recv_buffer = [];
|
this.recv_buffer = [];
|
||||||
this.recv_callback(full_data);
|
this.recv_callback(full_data, is_text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,17 +76,25 @@ class CurlWebSocket extends EventTarget {
|
||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_callback(data) {
|
recv_callback(data, is_text=false) {
|
||||||
if (this.binaryType == "blob") {
|
let converted;
|
||||||
data = new Blob(data);
|
if (is_text) {
|
||||||
}
|
converted = new TextDecoder().decode(data);
|
||||||
else if (this.binaryType == "arraybuffer") {
|
console.log(is_text);
|
||||||
data = data.buffer;
|
|
||||||
}
|
}
|
||||||
else {
|
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.onmessage(msg_event);
|
||||||
this.dispatchEvent(msg_event);
|
this.dispatchEvent(msg_event);
|
||||||
}
|
}
|
||||||
|
@ -118,6 +127,7 @@ class CurlWebSocket extends EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
send(data) {
|
send(data) {
|
||||||
|
let is_text = false;
|
||||||
if (this.status === this.CONNECTING) {
|
if (this.status === this.CONNECTING) {
|
||||||
throw new DOMException("ws not ready yet");
|
throw new DOMException("ws not ready yet");
|
||||||
}
|
}
|
||||||
|
@ -128,6 +138,7 @@ class CurlWebSocket extends EventTarget {
|
||||||
let data_array;
|
let data_array;
|
||||||
if (typeof data === "string") {
|
if (typeof data === "string") {
|
||||||
data_array = new TextEncoder().encode(data);
|
data_array = new TextEncoder().encode(data);
|
||||||
|
is_text = true;
|
||||||
}
|
}
|
||||||
else if (data instanceof Blob) {
|
else if (data instanceof Blob) {
|
||||||
data.arrayBuffer().then(array_buffer => {
|
data.arrayBuffer().then(array_buffer => {
|
||||||
|
@ -157,11 +168,24 @@ class CurlWebSocket extends EventTarget {
|
||||||
|
|
||||||
let data_ptr = allocate_array(data_array);
|
let data_ptr = allocate_array(data_array);
|
||||||
let data_len = data.length;
|
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);
|
_free(data_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
_close_websocket(this.http_handle);
|
_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
|
Loading…
Add table
Add a link
Reference in a new issue