Skip to content

Commit 36dbf1a

Browse files
authored
Merge pull request #7 from dblnz/add-js-guest
Add js guest
2 parents 78685ea + 5dc54af commit 36dbf1a

File tree

23 files changed

+5839
-667
lines changed

23 files changed

+5839
-667
lines changed

Cargo.lock

Lines changed: 715 additions & 552 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,23 @@ If you want to follow the manual build instructions, you will also need:
2222

2323
### Building
2424

25+
```sh
26+
# Install JS dependencies
27+
npm install
28+
```
29+
2530
```sh
2631
just build
2732
```
2833

2934
### Running
3035

3136
```sh
32-
just run
37+
# Run Rust
38+
just run-rust
39+
40+
# Run JS
41+
just run-js
3342
```
3443

3544
From another terminal, you can then test the server:
@@ -53,17 +62,22 @@ Compile the WIT and set the environment variables used when building
5362
wasm-tools component wit hyperlight.wit -w -o hyperlight-world.wasm
5463
```
5564

56-
Build:
65+
Build Rust:
5766
```
5867
cargo build
5968
```
6069

70+
Build JS:
71+
```
72+
npm run build
73+
```
74+
6175
### Running
6276

6377
Build the guest component:
6478
```sh
6579
cargo component build --release \
66-
--manifest-path guest/Cargo.toml \
80+
--manifest-path guest_rust/Cargo.toml \
6781
--target-dir target
6882
```
6983

@@ -73,11 +87,17 @@ AOT compile it:
7387
cargo install hyperlight-wasm-aot
7488
hyperlight-wasm-aot compile --component \
7589
target/wasm32-wasip1/release/sample_wasi_http_rust.wasm \
76-
target/wasm32-wasip1/release/sample_wasi_http_rust.bin
90+
out/sample_wasi_http_rust.aot
7791
```
7892

7993
You can then run the server:
8094

95+
Rust:
96+
```sh
97+
cargo run -- out/sample_wasi_http_rust.aot
98+
```
99+
100+
JS:
81101
```sh
82-
cargo run -- target/wasm32-wasip1/release/sample_wasi_http_rust.bin
102+
cargo run -- out/sample_wasi_http_js.aot
83103
```

eslint.config.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineConfig } from "eslint/config";
2+
import js from "@eslint/js";
3+
import globals from "globals";
4+
5+
export default defineConfig([
6+
{
7+
files: ["**/*.{js,mjs,cjs}"],
8+
plugins: { js },
9+
extends: ["js/recommended"],
10+
},
11+
{
12+
files: ["**/*.{js,mjs,cjs}"],
13+
languageOptions: { globals: globals.browser },
14+
},
15+
]);

guest_js/endpoints/echo.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export { echo, echoHeaders };
2+
3+
// Echo the body of the request in the response
4+
const echo = async (req) => {
5+
const bodyText = req.body ? await req.text() : "No body to echo";
6+
7+
return new Response(bodyText, {
8+
status: 200,
9+
headers: {
10+
"Content-Type": "text/plain",
11+
},
12+
});
13+
};
14+
15+
// Echo all headers from the request in JSON format
16+
const echoHeaders = (req) => {
17+
const headersObj = Object.fromEntries(req.headers.entries());
18+
return new Response(JSON.stringify(headersObj, null, 2), {
19+
status: 200,
20+
headers: {
21+
"Content-Type": "application/json",
22+
},
23+
});
24+
};

guest_js/endpoints/sleep.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export { sleep };
2+
3+
// Async sleep function that returns a response after waiting
4+
const sleep = async (ms) => {
5+
const msNum = parseInt(ms, 10);
6+
await new Promise((resolve) => setTimeout(resolve, msNum));
7+
8+
return new Response(`Sleeping for ${ms}ms...`, {
9+
status: 200,
10+
headers: {
11+
"Content-Type": "text/plain",
12+
},
13+
});
14+
};

guest_js/endpoints/upload.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
export { upload };
2+
3+
// Endpoint to handle file uploads using FormData and Blob
4+
const upload = async (req) => {
5+
try {
6+
const blob = await req.blob();
7+
8+
if (!blob || !(blob instanceof Blob)) {
9+
return new Response("File not found in form data.", { status: 400 });
10+
}
11+
12+
const text = await blob.text();
13+
14+
return new Response(text, {
15+
headers: {
16+
"Content-Type": blob.type || "application/octet-stream",
17+
},
18+
});
19+
} catch (error) {
20+
return new Response(`Error processing form data: ${error}`, {
21+
status: 500,
22+
});
23+
}
24+
};

guest_js/server.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { AutoRouter } from "itty-router";
2+
3+
import { sleep } from "./endpoints/sleep.js";
4+
import { upload } from "./endpoints/upload.js";
5+
import { echo, echoHeaders } from "./endpoints/echo.js";
6+
7+
let router = AutoRouter();
8+
9+
router
10+
.get("/", () => new Response("Hello, JS wasi:http world!\n"))
11+
.get("/echo-headers", (req) => echoHeaders(req))
12+
.get("/sleep/:ms", async ({ ms }) => await sleep(ms))
13+
.post("/echo", (req) => echo(req))
14+
.post("/upload", async (req) => await upload(req));
15+
16+
addEventListener("fetch", async (event) => {
17+
event.respondWith(router.fetch(event.request));
18+
});

0 commit comments

Comments
 (0)