From 5ab6ed30a242c9f0084672af6563dac767a47e57 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Mon, 27 Jan 2025 01:12:14 -0500 Subject: [PATCH] add code for main project website --- CHANGELOG.md | 7 +++ website/favicon.ico | Bin 0 -> 15086 bytes website/index.html | 88 ++++++++++++++++++++++++++++++++++ website/main.css | 112 ++++++++++++++++++++++++++++++++++++++++++++ website/main.js | 91 +++++++++++++++++++++++++++++++++++ 5 files changed, 298 insertions(+) create mode 100644 website/favicon.ico create mode 100644 website/index.html create mode 100644 website/main.css create mode 100644 website/main.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 4779c99..4b3eca6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Libcurl.js Changelog: +## v0.7.0 (1/24/25): +- Switch to Mbed TLS for the TLS backend + - This fixes some TLS certificate errors that were occurring on some sites with WolfSSL +- Fix a null pointer dereference bug with websockets +- Store the CA certificates bundle more efficiently +- The WASM size has decreased from 1.4MB to 1.2MB + ## v0.6.22 (1/10/25): - Remove Emscripten's maximum socket limit of 64 - Fix handling of sub-protocols in Websockets diff --git a/website/favicon.ico b/website/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a4e921b0d7f9c75d1ccda4d7c6307e67adba6871 GIT binary patch literal 15086 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 + + + + + libcurl.js - A port of libcurl to WASM for the web. + + + + + + + +
+

libcurl.js

+
+

libcurl.js is a port of the popular libcurl C library to WASM for use on the web. It allows you send encrypted HTTPS requests from the browser, without the proxy server being able to read the contents.

+

See the Github repository for more information.

+ + +

Features:

+
    +
  • Provides an API compatible with the browser's native Fetch API
  • +
  • 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 encrypted WebSockets
  • +
  • Bypass CORS restrictions without compromising on privacy
  • +
  • High performance and low latency via multiplexing and reusing open connections
  • +
  • Works in all major browsers (Chromium >= 64, Firefox >= 65, Safari >= 14)
  • +
  • Small footprint size (552KB after compression) and low runtime memory usage
  • +
  • Support for Brotli and gzip compressed responses
  • +
+ +

Live Demo:

+
+ + + +
+


Waiting for libcurl.js to load...

+ + + + + + + + + + + + + + + +
Request Content:Network Traffic:
+

+        
+
+
Libcurl Output:
+

+        
+ +

Explanation:

+

libcurl.js works by proxying TCP sockets, rather than HTTP requests. The Wisp protocol is used to multiplex the TCP connections over a single websocket for minimal latency. The libcurl C library is used as an HTTP client, and Mbed TLS is used to facilitate encryption.

+

If the destination server supports HTTPS, the connection will be end-to-end encrypted using TLS. Only the encrypted TLS traffic is carried over the websocket, so the proxy server knows nothing about your requests except for the hostname.

+

This avoids the privacy issues of a traditional CORS proxy which can steal your credentials and private information. With libcurl.js and Wisp, you don't need to trust the proxy server to keep your requests secure.

+ +

Javascript API:

+

Including libcurl.js in your web pages is as simple as loading the JS bundle using a script tag.

+
<script src="https://cdn.jsdelivr.net/npm/libcurl.js@latest/libcurl_full.js" defer></script>
+

Then, after setting the Websocket proxy URL, you can use the API to its full potential.

+
document.addEventListener("libcurl_load", ()=>{
+  libcurl.set_websocket(`wss://wisp.mercurywork.shop/`);
+  console.log("libcurl.js ready!");
+});
+

More documentation and examples are available on the project README.

+ +

License:

+

This project was written by ading2210 and it is licensed under the GNU LGPL v3.

+
+ This license is mainly applied to libraries. You may copy, distribute and modify the software provided that modifications are described and licensed for free under LGPL. Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL, but applications that use the library don't have to be. +

+ - From tldrlegal.com +
+ + \ No newline at end of file diff --git a/website/main.css b/website/main.css new file mode 100644 index 0000000..5e4144d --- /dev/null +++ b/website/main.css @@ -0,0 +1,112 @@ +:root { + --background-1: #0C0C0D; + --background-2: #18181A; + --background-3: #232327; + --button-color: #38383D; + --border-1: #3a344e; + --text-color: #cccccc; + --link-color: #3584E4; + --link-color-alt: #a64ede; +} + +* { + font-family: sans-serif; + color: var(--text-color); + border-color: var(--text-color); + box-sizing: border-box; +} + +a { + color: var(--link-color); +} +a:hover { + color: var(--link-color-alt); +} + +html { + background-color: var(--background-1); + height: 100%; + padding-left: 16px; + padding-right: 16px; +} + +body { + background-color: var(--background-2); + max-width: 800px; + min-height: 90%; + margin-top: 16px; + margin-left: auto; + margin-right: auto; + padding: 16px; +} + +h1, h2, h3 { + margin-bottom: 0px; +} + +pre, code { + font-family: monospace; + background-color: var(--background-1); + padding: 8px; + overflow-x: auto; +} + +table { + border-collapse: collapse; + table-layout: fixed; + width: 100%; +} +table, th, td { + border: 1px solid; + vertical-align: top; +} + +.center { + width: 100%; + text-align: center; +} +.button { + background-color: var(--button-color); +} + +#title { + margin-top: 0px; +} +#request_form { + display: flex; + gap: 4px; + width: 100%; + margin-bottom: 8px; + margin-top: 8px; +} +#url { + width: 100%; + background-color: var(--button-color); +} +#main_table { + visibility: hidden; + margin-bottom: 20px; +} +#network_data { + width: 100%; +} +#status_text { + height: 0px; + margin-top: 0px; + margin-bottom: 0px; +} + + +.list_cell { + height: 200px; + overflow-y: auto; + background-color: var(--background-3); +} +.list_cell pre { + height: 100%; + white-space: pre-wrap; + line-break: anywhere; + margin: 0px; + padding: 4px; + background-color: var(--background-3); +} \ No newline at end of file diff --git a/website/main.js b/website/main.js new file mode 100644 index 0000000..9c5d28d --- /dev/null +++ b/website/main.js @@ -0,0 +1,91 @@ +const decoder = new TextDecoder(); + +function from_id(id) { + return document.getElementById(id); +} + +async function start_request() { + let request_output = from_id("request_info"); + let libcurl_output = from_id("libcurl_output"); + let network_data = from_id("network_data"); + let url_box = from_id("url"); + + request_output.innerText = ""; + libcurl_output.innerText = ""; + network_data.innerText = ""; + + let url = url_box.value; + if (!url.startsWith("http://") && !url.startsWith("https://")) + url = "https://" + url; + request_output.innerText += `GET ${url}\n\n`; + + try { + let r = await libcurl.fetch(url, {_libcurl_verbose: 1}); + request_output.innerText += await r.text(); + } + catch (e) { + request_output.innerText += e; + } +} + +function handle_output(text) { + let output_element = from_id("libcurl_output"); + output_element.innerText += text + "\n"; + output_element.scrollTop = output_element.scrollHeight; +} + +function handle_ws_traffic(data, direction) { + let network_data = from_id("network_data"); + let table_row = document.createElement("tr"); + let direction_cell = document.createElement("td"); + let data_cell = document.createElement("td"); + let data_pre = document.createElement("pre"); + + if (direction === "send") + direction_cell.style.backgroundColor = "rgba(255, 0, 0, 0.3)"; + else if (direction === "recv") + direction_cell.style.backgroundColor = "rgba(0, 255, 0, 0.3)"; + direction_cell.style.fontFamily = "monospace"; + direction_cell.style.width = "36px"; + data_pre.style.fontSize = "10px"; + network_data.parentNode.style.display = "block"; + network_data.parentNode.style.marginBottom = "-2px"; + + data_cell.append(data_pre); + table_row.append(direction_cell, data_cell); + + direction_cell.innerText = direction; + data_pre.innerText = String.fromCodePoint(...new Uint8Array(data)); + network_data.append(table_row); +} + +function proxy_websocket() { + WebSocket.prototype.send = new Proxy(WebSocket.prototype.send, { + apply(a, b, c) { + handle_ws_traffic(c[0], "send"); + Reflect.apply(a, b, c); + }} + ); + WebSocket = new Proxy(WebSocket, { + construct(target, args) { + let ws = new target(...args); + ws.addEventListener("message", (event) => { + handle_ws_traffic(event.data, "recv"); + }); + return ws; + }} + ); +} + +document.addEventListener("libcurl_load", () => { + console.log(`loaded libcurl.js ${libcurl.version.lib}`); + + libcurl.set_websocket("wss://wisp.mercurywork.shop/"); + libcurl.stdout = handle_output; + libcurl.stderr = handle_output; + proxy_websocket(); + + from_id("status_text").style.display = "none"; + from_id("main_table").style.visibility = "visible"; + start_request(); +}); \ No newline at end of file