diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 74567d2..013f502 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: - name: run tests working-directory: ./client - run: ./tests/run.sh || true + run: ./tests/run.sh - name: upload img uses: actions/upload-artifact@v4 diff --git a/README.md b/README.md index 4bac323..910dee1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ cd libcurl.js/client ``` Make sure you have emscripten, git, and the various C build tools installed. The only OS supported for building libcurl.js is Linux. On Debian-based systems, you can run the following command to install all the dependencies: ``` -sudo apt install make cmake emscripten autoconf automake libtool pkg-config wget xxd +sudo apt install make cmake emscripten autoconf automake libtool pkg-config wget xxd jq ``` The build script will generate `client/out/libcurl.js` as well as `client/out/libcurl.mjs`, which is an ES6 module. You can supply the following arguments to the build script to control the build: @@ -51,7 +51,7 @@ document.addEventListener("libcurl_load", ()=>{ }); ``` -Once loaded, there will be a `window.libcurl` object which includes all the API functions. +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. ### Making HTTP Requests: To perform HTTP requests, use `libcurl.fetch`, which takes the same arguments as the browser's regular `fetch` function. Like the standard Fetch API, `libcurl.fetch` will also return a `Response` object. @@ -96,6 +96,9 @@ By default this will print the output to the browser console, but you can set `l libcurl.stderr = (text) => {document.body.innerHTML += text}; ``` +### Getting Version Info: +You can get version information from the `libcurl.version` object. This object will also contain the versions of all the C libraries that libcurl.js uses. `libcurl.version.lib` returns the version of libcurl.js itself. + ## Proxy Server: The proxy server consists of a standard [Wisp](https://github.com/MercuryWorkshop/wisp-protocol) server, allowing multiple TCP connections to share the same websocket. @@ -106,7 +109,7 @@ cd libcurl.js server/run.sh --static=./client ``` -You can use the `HOST` and `PORT` environment variables to control the hostname and port that the proxy server listens on. +For a full list of server arguments, see the [wisp-server-python documentation](https://github.com/MercuryWorkshop/wisp-server-python). ## Copyright: This project is licensed under the GNU AGPL v3. diff --git a/client/build.sh b/client/build.sh index 76bf163..5f0e7fe 100755 --- a/client/build.sh +++ b/client/build.sh @@ -75,6 +75,10 @@ cp $JAVSCRIPT_DIR/main.js $OUT_FILE sed -i "/__emscripten_output__/r $MODULE_FILE" $OUT_FILE rm $MODULE_FILE +#set version number +VERSION=$(cat package.json | jq -r '.version') +sed -i "s/__library_version__/$VERSION/" $OUT_FILE + #add extra libraries sed -i "/__extra_libraries__/r $WISP_CLIENT/polyfill.js" $OUT_FILE sed -i "/__extra_libraries__/r $WISP_CLIENT/wisp.js" $OUT_FILE diff --git a/client/exported_funcs.txt b/client/exported_funcs.txt index 9b8c19a..f437e28 100644 --- a/client/exported_funcs.txt +++ b/client/exported_funcs.txt @@ -3,6 +3,8 @@ start_request tick_request active_requests +get_version + recv_from_websocket send_to_websocket close_websocket diff --git a/client/javascript/main.js b/client/javascript/main.js index f989e8e..15c3f43 100644 --- a/client/javascript/main.js +++ b/client/javascript/main.js @@ -33,12 +33,14 @@ var websocket_url = null; var event_loop = null; var active_requests = 0; var wasm_ready = false; +var version_dict = null; +const libcurl_version = "__library_version__"; -function check_loaded() { +function check_loaded(check_websocket) { if (!wasm_ready) { throw new Error("wasm not loaded yet, please call libcurl.load_wasm first"); } - if (!websocket_url) { + if (!websocket_url && check_websocket) { throw new Error("websocket proxy url not set, please call libcurl.set_websocket"); } } @@ -258,7 +260,7 @@ function perform_request_async(url, params, body) { } async function libcurl_fetch(url, params={}) { - check_loaded(); + check_loaded(true); let body = await create_options(params); return await perform_request_async(url, params, body); } @@ -273,6 +275,18 @@ function set_websocket_url(url) { else Module.websocket.url = url; } +function get_version() { + if (!wasm_ready) return null; + if (version_dict) return version_dict; + + let version_ptr = _get_version(); + let version_str = UTF8ToString(version_ptr); + _free(version_ptr); + version_dict = JSON.parse(version_str); + version_dict.lib = libcurl_version; + return version_dict; +} + function main() { wasm_ready = true; _init_curl(); @@ -295,10 +309,13 @@ return { load_wasm: load_wasm, wisp: _wisp_connections, WebSocket: CurlWebSocket, + + get version() {return get_version()}, get stdout() {return out}, set stdout(callback) {out = callback}, get stderr() {return err}, - set stderr(callback) {err = callback} + set stderr(callback) {err = callback}, + get ready() {return wasm_ready} } })() \ No newline at end of file diff --git a/client/javascript/websocket.js b/client/javascript/websocket.js index d60fb22..76ee79e 100644 --- a/client/javascript/websocket.js +++ b/client/javascript/websocket.js @@ -3,7 +3,7 @@ class CurlWebSocket extends EventTarget { constructor(url, protocols=[]) { super(); - check_loaded(); + check_loaded(true); if (!url.startsWith("wss://") && !url.startsWith("ws://")) { throw new SyntaxError("invalid url"); } diff --git a/client/libcurl/util.c b/client/libcurl/util.c index efa21ff..c991858 100644 --- a/client/libcurl/util.c +++ b/client/libcurl/util.c @@ -1,5 +1,36 @@ +#include +#include #include +#include "curl/curl.h" +#include "cjson/cJSON.h" + int starts_with(const char *a, const char *b) { return strncmp(a, b, strlen(b)) == 0; +} + +char* get_version() { + struct curl_version_info_data *version_info = curl_version_info(CURLVERSION_NOW); + cJSON* version_json = cJSON_CreateObject(); + + cJSON* protocols_array = cJSON_CreateArray(); + const char *const *protocols = version_info->protocols; + for (; *protocols != NULL; protocols++) { + cJSON* protocol_item = cJSON_CreateString(*protocols); + cJSON_AddItemToArray(protocols_array, protocol_item); + } + + cJSON* curl_version_item = cJSON_CreateString(version_info->version); + cJSON* ssl_version_item = cJSON_CreateString(version_info->ssl_version); + cJSON* brotli_version_item = cJSON_CreateString(version_info->brotli_version); + cJSON* nghttp2_version_item = cJSON_CreateString(version_info->nghttp2_version); + + cJSON_AddItemToObject(version_json, "curl", curl_version_item); + cJSON_AddItemToObject(version_json, "ssl", ssl_version_item); + cJSON_AddItemToObject(version_json, "brotli", brotli_version_item); + cJSON_AddItemToObject(version_json, "nghttp2", nghttp2_version_item); + cJSON_AddItemToObject(version_json, "protocols", protocols_array); + + char* version_json_str = cJSON_Print(version_json); + return version_json_str; } \ No newline at end of file diff --git a/client/package.json b/client/package.json index 52990f7..1535226 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "libcurl.js", - "version": "0.2.0", + "version": "0.3.0", "description": "An experimental port of libcurl to WebAssembly for use in the browser.", "main": "libcurl.mjs", "scripts": { diff --git a/client/publish.sh b/client/publish.sh index 58ae332..8f601bc 100755 --- a/client/publish.sh +++ b/client/publish.sh @@ -3,8 +3,11 @@ #publish libcurl.js as an npm package ./build.sh all +tests/run.sh cp package.json out cp ../README.md out +cp ../LICENSE out + cd out npm publish \ No newline at end of file diff --git a/server/run.sh b/server/run.sh index 981c682..94d0ae1 100755 --- a/server/run.sh +++ b/server/run.sh @@ -14,7 +14,7 @@ fi source $SERVER_PATH/.venv/bin/activate if ! python3 -c "import websockets" 2> /dev/null; then - pip3 install -r requirements.txt + pip3 install -r $SERVER_PATH/requirements.txt fi python3 $SERVER_PATH/main.py "$@" \ No newline at end of file