add nodejs support

This commit is contained in:
ading2210 2025-02-13 16:12:03 -05:00
parent 3a2ab40e75
commit 87b887a4b7
13 changed files with 78 additions and 18 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
/client/build /client/build
/client/out /client/out
/client/fragments/tmp /client/fragments/tmp
/client/node_modules
/server/.venv /server/.venv
/server/websockify /server/websockify

View file

@ -39,7 +39,7 @@ This is a port of [libcurl](https://curl.se/libcurl/) to WebAssembly for use in
- Use raw TLS sockets in the browser - Use raw TLS sockets in the browser
- Custom network transport support - Custom network transport support
- Works inside web workers without needing special permissions or headers - Works inside web workers without needing special permissions or headers
- Works in all major browsers (Chromium >= 64, Firefox >= 65, Safari >= 14) - Works in all major browsers (Chromium >= 64, Firefox >= 65, Safari >= 14) and Node.js
- Has the ability to create multiple independent sessions - Has the ability to create multiple independent sessions
- Small footprint size (552KB after compression) and low runtime memory usage - Small footprint size (552KB after compression) and low runtime memory usage
- Support for Brotli and gzip compressed responses - Support for Brotli and gzip compressed responses
@ -107,7 +107,7 @@ libcurl.onload = () => {
Once loaded, there will be a `window.libcurl` object which includes all the API functions. The `libcurl.ready` property can also be used to know if the WASM has loaded. Once loaded, there will be a `window.libcurl` object which includes all the API functions. The `libcurl.ready` property can also be used to know if the WASM has loaded.
There are also ES6 modules available if you are using a bundler. The `libcurl.mjs` and `libcurl_full.mjs` files provide this functionality, with the former being set as the entry point for the NPM package. There are also ES6 modules available if you are using a bundler or running it in NodeJS. The `libcurl.mjs` and `libcurl_full.mjs` files provide this functionality, with the former being set as the entry point for the NPM package.
```js ```js
//import the regular version //import the regular version
import { libcurl } from "libcurl.js"; import { libcurl } from "libcurl.js";

View file

@ -38,7 +38,7 @@ EXPORTED_FUNCS="${EXPORTED_FUNCS:1}"
#compile options #compile options
RUNTIME_METHODS="addFunction,removeFunction,allocate,ALLOC_NORMAL" RUNTIME_METHODS="addFunction,removeFunction,allocate,ALLOC_NORMAL"
COMPILER_OPTIONS="-o $MODULE_FILE -lcurl -lmbedtls -lmbedcrypto -lmbedx509 -lcjson -lz -lbrotlidec -lbrotlicommon -lnghttp2 -I $INCLUDE_DIR -L $LIB_DIR" COMPILER_OPTIONS="-o $MODULE_FILE -lcurl -lmbedtls -lmbedcrypto -lmbedx509 -lcjson -lz -lbrotlidec -lbrotlicommon -lnghttp2 -I $INCLUDE_DIR -L $LIB_DIR"
EMSCRIPTEN_OPTIONS="-lwebsocket.js -sENVIRONMENT=worker,web -sASSERTIONS=1 -sLLD_REPORT_UNDEFINED -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH -sNO_EXIT_RUNTIME -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS -sEXPORTED_RUNTIME_METHODS=$RUNTIME_METHODS" EMSCRIPTEN_OPTIONS="-lwebsocket.js -sENVIRONMENT=node,worker,web -sASSERTIONS=1 -sLLD_REPORT_UNDEFINED -sALLOW_TABLE_GROWTH -sALLOW_MEMORY_GROWTH -sNO_EXIT_RUNTIME -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS -sEXPORTED_RUNTIME_METHODS=$RUNTIME_METHODS"
#clean output dir #clean output dir
rm -rf $OUT_DIR rm -rf $OUT_DIR
@ -122,5 +122,6 @@ sed -i "/__extra_libraries__/r $WISP_CLIENT/wisp.js" $OUT_FILE
python3 tools/patch_js.py $FRAGMENTS_DIR $OUT_FILE python3 tools/patch_js.py $FRAGMENTS_DIR $OUT_FILE
#generate es6 module #generate es6 module
cp $OUT_FILE $ES6_FILE cp "$OUT_FILE" "$ES6_FILE"
sed -i 's/const libcurl = /export const libcurl = /' $ES6_FILE sed -i 's/export const libcurl = /const libcurl = /' "$OUT_FILE"
sed -i 's/export default libcurl;//' "$OUT_FILE"

View file

@ -0,0 +1,10 @@
/* REPLACE
__dirname
*/
globalThis.__dirname
/* DELETE
if ?\(ENVIRONMENT_IS_NODE\) ?{\s*peer\.socket\.on.+?else ?(?={\s*peer\.socket\.onopen)
*/

View file

@ -12,3 +12,8 @@ var parts = addr.split("/");
url = Module.websocket.url; url = Module.websocket.url;
if (!url.endsWith("/")) url += "/"; if (!url.endsWith("/")) url += "/";
url += parts[0] + ":" + port; url += parts[0] + ":" + port;
/* DELETE
var WebSocketConstructor.+?WebSocketConstructor ?= ?WebSocket;?\s*}
*/

View file

@ -3,10 +3,10 @@ ws ?= ?new WebSocketConstructor\(url, ?opts\)
*/ */
try { try {
if (api.transport === "wisp") { if (api.transport === "wisp") {
ws = new WispWebSocket(url); ws = new WispWebSocket(url, WSImpl);
} }
else if (api.transport === "wsproxy") { else if (api.transport === "wsproxy") {
ws = new WebSocket(url); ws = new WSImpl(url);
} }
else if (typeof api.transport === "string") { else if (typeof api.transport === "string") {
throw new TypeError("invalid transport type"); throw new TypeError("invalid transport type");

View file

@ -193,7 +193,7 @@ class HTTPSession extends CurlSession {
if (params.referrer) { if (params.referrer) {
params.headers["Referer"] = params.referrer; params.headers["Referer"] = params.referrer;
} }
if (!params.headers["User-Agent"]) { if (!params.headers["User-Agent"] && typeof navigator === "object") {
params.headers["User-Agent"] = navigator.userAgent; params.headers["User-Agent"] = navigator.userAgent;
} }
if (body && !params.headers["Content-Type"]) { if (body && !params.headers["Content-Type"]) {

View file

@ -5,7 +5,7 @@ Licensed under the GNU LGPL v3. See https://github.com/ading2210/libcurl.js
*/ */
//everything is wrapped in a function to prevent emscripten from polluting the global scope //everything is wrapped in a function to prevent emscripten from polluting the global scope
const libcurl = (function() { export const libcurl = (function() {
//emscripten compiled code is inserted here //emscripten compiled code is inserted here
/* __emscripten_output__ */ /* __emscripten_output__ */
@ -21,6 +21,8 @@ var main_session = null;
const libcurl_version = "__library_version__"; const libcurl_version = "__library_version__";
const wisp_version = "__wisp_version__"; const wisp_version = "__wisp_version__";
const WSImpl = (typeof process !== "undefined" && typeof WebSocket === "undefined") ? require("ws").WebSocket : WebSocket;
function check_loaded(check_websocket) { function check_loaded(check_websocket) {
if (!wasm_ready) { if (!wasm_ready) {
throw new Error("wasm not loaded yet, please call libcurl.load_wasm first"); throw new Error("wasm not loaded yet, please call libcurl.load_wasm first");
@ -149,4 +151,6 @@ api = {
return api; return api;
})() })()
export default libcurl;

View file

@ -186,7 +186,7 @@ class CurlSession {
try { try {
stream_controller.close(); stream_controller.close();
} }
catch {} catch (e) {}
end_callback(error); end_callback(error);
} }

36
client/package-lock.json generated Normal file
View file

@ -0,0 +1,36 @@
{
"name": "libcurl.js",
"version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "libcurl.js",
"version": "0.7.0",
"license": "LGPL-3.0-or-later",
"dependencies": {
"ws": "^8.18.0"
}
},
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}

View file

@ -1,6 +1,6 @@
{ {
"name": "libcurl.js", "name": "libcurl.js",
"version": "0.7.0", "version": "0.7.1",
"description": "A port of libcurl to WebAssembly, for proxying HTTPS requests from the browser with full TLS encryption", "description": "A port of libcurl to WebAssembly, for proxying HTTPS requests from the browser with full TLS encryption",
"main": "libcurl.mjs", "main": "libcurl.mjs",
"exports": { "exports": {
@ -16,5 +16,8 @@
"bugs": { "bugs": {
"url": "https://github.com/ading2210/libcurl.js/issues" "url": "https://github.com/ading2210/libcurl.js/issues"
}, },
"homepage": "https://github.com/ading2210/libcurl.js" "homepage": "https://github.com/ading2210/libcurl.js",
"dependencies": {
"ws": "^8.18.0"
}
} }

View file

@ -16,14 +16,14 @@ for fragment_file in fragments_path.iterdir():
matches = re.findall(match_regex, fragment_text, re.S) matches = re.findall(match_regex, fragment_text, re.S)
for mode, patch_regex, patch_text, _ in matches: for mode, patch_regex, patch_text, _ in matches:
fragment_matches = re.findall(patch_regex, target_text) fragment_matches = re.findall(patch_regex, target_text, flags=re.S)
if not fragment_matches: if not fragment_matches:
print(f"warning: regex did not match anything for '{patch_regex}'"); print(f"warning: regex did not match anything for '{patch_regex}'");
if mode == "DELETE": if mode == "DELETE":
target_text = re.sub(patch_regex, "", target_text) target_text = re.sub(patch_regex, "", target_text, flags=re.S)
elif mode == "REPLACE": elif mode == "REPLACE":
target_text = re.sub(patch_regex, patch_text, target_text) target_text = re.sub(patch_regex, patch_text, target_text, flags=re.S)
elif mode == "INSERT": elif mode == "INSERT":
target_text = re.sub("("+patch_regex+")", r'\1'+patch_text, target_text) target_text = re.sub("("+patch_regex+")", r'\1'+patch_text, target_text, flags=re.S)
target_path.write_text(target_text) target_path.write_text(target_text)

@ -1 +1 @@
Subproject commit 455b9186bfbd0915ed7082c9d356af2157ab014f Subproject commit 993e0556fbac89a2bb8cfcbe72f687ed5a15b0da